静态成员
静态成员的访问有两种:
1.通过对象访问
2.通过类名访问
对于这两个方法,第一种与非静态成员是一样的,可以验证一下第二种——通过类名访问:
#include<iostream> using namespace std; class A { public: static void a() { cout << "父类中调用" << endl; } }; class A1:public A { public: static void a() { cout << "子类中调用" << endl; } }; void test1() { A1 a1; A1::a(); A1::A::a(); } int main() { test1(); return 0; }
静态函数发生函数重载时也与非静态函数发生函数重载一样。
多继承
在C++种,允许一个类继承多个类,这个时候就是多继承
语法
class 子类: 继承方式 父类1 , 继承方式 父类2 …
注意
在多继承中,多个父类中可能有同名成员出现,这个时候需要加作用域来区分
多继承中的对象模型
那当子类继承多个父类的时候,每个父类内的非静态成员都会被继承过去吗?通过代码验证一下:
#include<iostream> using namespace std; class A { public: int a; int b; }; class A1 { public: int _a; int _b; }; class AA :public A, public A1 { public: int _a1; int _b1; }; void test1() { AA aa; cout << sizeof(aa) << endl; } int main() { test1(); return 0; }
和普通继承一样,每个父类的非静态成员都会被继承到子类当中。
多继承父类成员名相同
假设现在两个父类,有两个成员名时一样的,那子类能直接访问这个成员吗?
#include<iostream> using namespace std; class A { public: int _a; int b; }; class A1 { public: int _a; int _b; }; class AA :public A, public A1 { public: int _a1; int _b1; }; void test1() { AA aa; aa._a; } int main() { test1(); return 0; }
编译器是直接报错的,是因为编译器不知道这个成员是来自与哪个父类,这个情况在C++中有个专业名词,叫做二义性,这个时候要怎么样才能访问到呢?就需要进行加作用域,假设现在访问A内的_a:
#include<iostream> using namespace std; class A { public: int _a; int b; }; class A1 { public: int _a; int _b; }; class AA :public A, public A1 { public: int _a1; int _b1; }; void test1() { AA aa; aa.A::_a = 10; cout<<aa.A::_a<<endl; } int main() { test1(); return 0; }
菱形继承
概念
两个子类继承了同一个父类,又有一个类,同时继承了两个子类
菱形继承出现的问题
马和驴都继承了动物的数据,在骡子使用数据的时候,就会产生二义性,骡子继承动物的数据只需要一份,那应该怎么办?
虚继承
对于上面所说的二义性的问题,因为同样的数据只需要一份,这个时候就可以在继承的时候加上关键字:
vritual
将继承变成虚继承,这个时候最大的父类就为虚基类,可以用代码试验:
#include<iostream> using namespace std; class A { public: int a; int b; }; class AA:virtual public A { }; class AA1:virtual public A { }; class AAA :public AA, public AA1 { }; void test1() { AAA a; a.AA::a = 10; a.AA1::a = 20; cout << a.AA::a << endl; cout << a.AA1::a << endl; } int main() { test1(); return 0; }
发现,两个数据修改输出的结果是一样的,这个时候就是虚继承起到的作用,让将内部数据共享了一个,这个时候最小的子类也可以直接访问到这个属性:
#include<iostream> using namespace std; class A { public: int a; int b; }; class AA:virtual public A { }; class AA1:virtual public A { }; class AAA :public AA, public AA1 { }; void test1() { AAA a; a.AA::a = 10; a.AA1::a = 20; cout << a.a << endl; } int main() { test1(); return 0; }
这是为什么呢?那这个时候从父类继承下来些什么?这个时候从父类继承下来一个指针:
vbptr
这个指针叫做虚基类指针,它会指向一个叫做:
vbtable
虚基类表,虚基类表中有一个偏移量,这个偏移量会指向一个数据,每个子类指向的数据都是同一份,这个时候数据就只会有一个。
步入第七层
石碑倒下,大片尘土飞扬,尘土散去,只留下一串脚印,通往第七层…
本章知识点(图片形式)
😘预知后事如何,关注新专栏,和我一起征服C++这座巨塔
🚀专栏:C++爬塔日记
🙉都看到这里了,留下你们的👍点赞+⭐收藏+📋评论吧🙉