C++继承与派生--访问控制
说明:以下实验证明一个是出自以Person类为父类,Student为子类的源代码,另一个出自以Point为父类,Recetangle为子类的源代码
派生类生成过程
1.吸收基类成员
2.改造基类成员
3.添加新成员
过程三步骤详述
-
吸收基类成员
派生过程中构造函数和析构函数都不被继承,因此在对派生类新增成员进行初始化,需要在派生类写构造函数负责对新增成员的初始化,而从基类继承的成员,依旧由基类的构造函数完成 -
改造基类成员
(1)基类成员的访问问题,靠继承方式控制
(2)对基类数据或函数成员的覆盖和隐藏,如果派生类声明了一个和某个基类成员同名的新成员(注:函数要参数相同,如果不同的话,就是函数重载),派生的新成员会隐藏基类中同名的函数,并且在类外通过生成对象来直接使用成员名时,基类的成员就会被隐藏,即同名隐藏
同名隐藏
同名隐藏前:
同名隐藏后:
- 添加新成员
通过派生类中新成员派生类新功能的实现:
Person类中的成员函数:
Student类中的成员函数:
访问控制
- 继承语法:
Class 派生类名:继承方式(public private protected) 基类名{} - 分类:
(1)公有继承:(常用)
当类的继承方式是公有继承,即public时,父类中public和protected中的成员访问属性不变,而父类private中的成员在子类中不能直接访问,可通过从父类中继承的公共接口对此进行操作
私有成员报错
公有和保护成员不报错
(2)私有继承:(不常用)
当类的继承方式是私有继承,即private时,父类的公有成员和保护成员以私有成员的身份出现在子类中,在子类内部可以互相互访问,但在类外通过对象就不能访问和操作,而父类private中的成员在子类中还是子类外都不能直接访问经过私有继承后,父类中的成员成为子类私有成员或者不可直接访问的成员,那么如果进一步派生的话,基类的全部成员就无法在新的派生类中直接访问
子类内部不报错
通过对象访问报错
(3)保护继承:
当类的继承方式是保护继承,即protected时,父类的公有成员和保护成员以保护成员的身份出现在子类中,在子类内部可以互相访问,但在类外通过对象就不能访问和操作,而父类private中的成员在子类中还是子类外都不能直接访问
子类内部不报错
通过对象访问报错
以上所有实验的代码
以Point类为父类,Recetangle为子类的源代码
头文件声明:
#ifndef POINT_H
#define POINT_H
//Point类定义
class Point
{
public:
void initP(float xx , float yy ) ;
void move(float xoff, float yoff);
float getX() const;
float getY() const;
private:
float x, y;
};
//retangle类定义
class Recetangle:private Point
{
public:
void initR(float x, float y, float w, float h);
float getWidth() const;
float getHeight() const;
private:
float w, h;
};
头文件函数实现:
#include "point.h"
#include<iostream>
using namespace std;
//point类函数实现
void Point::initP(float xx=0, float yy = 0)
{
x=xx;
y=yy;
}
void Point::move(float xoff, float yoff)
{
x += xoff;
y += yoff;
}
float Point::getX() const
{
return x;
}
float Point::getY() const
{
return y;
}
//Recetangle类函数实现
void Recetangle::initR(float x, float y, float w, float h)
{
initP(x, y);//私有继承,公有成员子类内部可以访问
this->w = w;
this->h = h;
}
float Recetangle::getHeight() const
{
return h;
}
float Recetangle::getWidth() const
{
return w;
}
main函数:
#include"point.h"
#include <iostream>
using namespace std;
int main()
{
/*Recetangle test;
test.initR(2, 3, 20, 30);
test.move(3, 2);
cout << test.getX() << " "
<< test.getY ()<< " "
<< test.getWidth() << " "
<<test.getHeight() << " "
<< endl;*/
//Recetangle test2;
//test2.getX();//以私有继承,在类外通过对象进行访问,编译器报错
//test2.getY();
//Recetangle test3;
//test3.getX();
//test3.initP();//以保护继承,在类外不能通过对象访问
return 0;
}
以Person类为父类,Student为子类的源代码
头文件声明:
#ifndef PCH_H
#define PCH_H
#include<string>
using namespace std;
class Person
{
public:
Person();
~Person();
void Inputinfo();
void Showinfo() const;
private:
string name;
protected:
int age;
};
class Student:public Person
{
public:
Student();
void Inputinfo2();
//void Inputinfo();//同名隐藏实验
void Showinfo2() const;
private:
float grades;
int id;
};
头文件中函数实现:
#include "pch.h"
#include<iostream>
#include<string>
using namespace std;
/****Person类成员函数实现****/
//功能:构造函数
Person::Person():name(name),age(age){}
//功能:析构函数,人数减1
Person::~Person(){}
//功能:输入用户名字、年龄
void Person::Inputinfo()
{
cout << "Pleasing input your name" << endl;
cin >> name;
cout << "Pleasing input your age" << endl;
cin >> age;
}
//功能:显示用户名字、年龄
void Person::Showinfo() const
{
cout << "用户名: " << name << " \t " << "年龄 :" << age;
}
/****Student类成员函数的实现****/
//功能:Student类中构造函数实现
Student::Student():id(id),grades(grades){}
//功能:输入学生名字、年龄、学号、成绩
void Student::Inputinfo2()
{
Inputinfo();
cout << "Pleasing input your id" << endl;
cin >> id;
cout << "Pleasing input your grades" << endl;
cin >> grades;
}
////功能:输入学生学号、成绩(实现同名隐藏,通过对象操作时同名函数采取就近原则)
//void Student::Inputinfo()
//{
// cout << "Pleasing input your id" << endl;
// cin >> id;
// cout << "Pleasing input your grades" << endl;
// cin >> grades;
//}
//功能:显示学生名字、年龄、学号、成绩
void Student::Showinfo2() const
{
Showinfo();
cout << "\t";
cout << "学号: " << id << " \t " << "成绩: " << grades << endl;
}
////测试子类不能直接访问父类私有成员,编译器报错
//void Student::Showinfo2() const
//{
// cout << name
// << age;
//}
////测试以public继承,父类的公有成员和保护成员在子类内部可以直接访问,编译器不报错
//void Student::Showinfo2() const
//{
// Showinfo();//父类公有成员
// cout << age;//在做这步实验时,将原本私有成员的age改成了保护成员
// cout << "\t";
// cout << "学号: " << id << " \t " << "成绩: " << grades << endl;
//}
main函数:
#include "pch.h"
#include <iostream>
#include<string>
using namespace std;
int main()
{
/*Person p1;
p1.Inputinfo();
p1.Showinfo();*/
Student stu1;
//stu1.Inputinfo();//同名隐藏前,原本Person类中Inputinfo函数输入的是name和age
stu1.Inputinfo2();
stu1.Showinfo2();
return 0;
}