目录
继承概念
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保
持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象
程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继
承是类设计层次的复用。
格式
继承特性
继承后成员访问的方式的变化
tip:
1.使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过
最好显示的写出继承方式。
2. 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡
使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里
面使用,实际中扩展维护性不强。
3. 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在
派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
4.根据上面这个表格其实可以发现,我们继承的时候是去取最小的访问限定。比如一个函数的权限是protected用public方式继承后访问限定任然是protected。
子父类成员重命名
子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,
也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)
class peopel {
protected:
string name="111";
};
class teacher : public peopel {
void show()
{
cout <<name<<peopel::name;
}
protected:
string name="222";
};
如果我们不指定就是子类里面的name
派生类的默认成员函数
1.对于构造函数,父类不显示的写,会去调用自己的默认构造,子类回去调用自己的默认构造,注意这个过程是先完成父类的构造,再完成子类的构造。
如:
class Person {
public:
Person(const string& name="牢大") :
_name(name)
{}
Person(const Person& data): _name(data._name)
{}
virtual~Person() {
};
protected:
string _name;
};
class Student :public Person {
public:
Student( const string& name="", const string& id="") : _id(id) {}
Student(const Student&data):Person::Person(data),_id(data._id){}
void Show()
{
cout << _id << _name;
}
virtual~Student() {};
protected:
string _id;
};
void Test2()
{
Student st1("zgw", "444");
st1.Show();
}
这里我们就算是写了这个参数,也只会去执行无参的默认构造。
只有当我们去显示的写了传参才有用。
2.拷贝构造同上。
3.析构函数,派生类对象析构清理先调用派生类析构再调基类的析构。因为后续一些场景析构函数需要构成重写,重写的条件之一是函数名相同(这个我后面会讲解)。那么编译器会对析构函数名进行特殊处理,处理成destrutor(),所以父类析构函数加virtual的情况下,子类析构函数和父类析构函数构成隐藏关系。这里有一些多态的知识。
class Person {
public:
Person(const string& name="牢大") :
_name(name)
{}
Person(const Person& data): _name(data._name)
{}
~Person() {
cout << "~Person()" << endl;
};
protected:
string _name;
};
class Student :public Person {
public:
Student( const string& name="", const string& id="") :Person::Person(name), _id(id) {}
Student(const Student&data):Person::Person(data),_id(data._id){}
void Show()
{
cout << _id << _name;
}
~Student() {
cout << "~Student()" << endl;
};
protected:
string _id;
};
void Test2()
{
Student st1("zgw", "444");
st1.Show();
}
菱形继承
当我们写出这样的代码:
这样的继承,Assistant里面就有两份Person的数据,这样就出现了数据冗余和二义性,现实世界其实有这种场景如一个导员既是学生又是老师,但是写代码不建议这么写,所以出现这种情况我们一般用虚继承
如:
class person
{
public:
string _name; // 姓名
};
class student : virtual public person
{
protected:
int _num; //学号
};
class Teacher : virtual public person
{
protected:
int _id; // 职工编号
};
class Assistant : public student, public Teacher
{
protected:
string _majorCourse; // 主修课程
};
void Test3()
{
Assistant a;
a._name = "peter";
cout << a._name;
}
这样就不会出现二义性。
小tip
1.基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子
类,都只有一个static成员实例 。
2.友元函数不能被继承。
标签:name,继承,成员,c++,class,Person,菱形,public From: https://blog.csdn.net/zgwnb666/article/details/140292461