您的位置:首页 > 财经 > 金融 > c++继承特点,菱形继承,访问方式,默认成员函数

c++继承特点,菱形继承,访问方式,默认成员函数

2025/2/24 8:18:50 来源:https://blog.csdn.net/zgwnb666/article/details/140292461  浏览:    关键词:c++继承特点,菱形继承,访问方式,默认成员函数

目录

继承概念

继承特性

继承后成员访问的方式的变化

子父类成员重命名

派生类的默认成员函数

​编辑

菱形继承

小tip


继承概念

继承(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.友元函数不能被继承。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com