继承同名成员处理方式
问题:
当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据呢?
- 访问子类同名成员 直接访问即可(就近原则,正常访问的是子类的)
- 访问父类同名成员 需要加作用域
class Base { public: Base() { m_A = 100; } void func() { cout << "Base - func()调用" << endl; } void func(int a) { cout << "Base - func(int a)调用" << endl; } public: int m_A; }; class Son : public Base { public: Son() { m_A = 200; } //如果想访问父类中被隐藏的同名成员函数,需要加父类的作用域 void func() { cout << "Son - func()调用" << endl; } public: int m_A; }; void test01() { Son s; cout << "Son下的m_A = " << s.m_A << endl; cout << "Base下的m_A = " << s.Base::m_A << endl; s.func(); s.Base::func(); //当子类与父类拥有同名的成员函数,子类会隐藏父类中所有版本的同名成员函数(只要是func的全部隐藏,不能直接访问),想要访问只能加作用域。 s.func(100); //报错 s.Base::func(10); } int main() { test01(); system("pause"); return EXIT_SUCCESS; }
总结:
- 子类对象可以直接访问到子类中同名成员
- 子类对象加作用域可以访问到父类同名成员
- 当子类与父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数
继承同名静态成员处理方式
问题:
继承中同名的静态成员在子类对象上如何进行访问?
静态成员和非静态成员出现同名,处理方式一致
- 访问子类同名成员 直接访问即可
- 访问父类同名成员 需要加作用域
示例:
class Base { public: static void func() { cout << "Base - static void func()" << endl; } static void func(int a) { cout << "Base - static void func(int a)" << endl; } //静态成员属性(编译阶段分配到内存,所有对象共享同一份数据) static int m_A; }; //类内声明,类外初始化 int Base::m_A = 100; class Son : public Base { public: static void func() { cout << "Son - static void func()" << endl; } static int m_A; }; int Son::m_A = 200; //同名成员属性 void test01() { //通过对象访问 cout << "通过对象访问: " << endl; Son s; cout << "Son 下 m_A = " << s.m_A << endl; cout << "Base 下 m_A = " << s.Base::m_A << endl; //通过类名访问(静态成员变量专属福利) cout << "通过类名访问: " << endl; cout << "Son 下 m_A = " << Son::m_A << endl; //第一个::代表通过类目方式访问,第二个::代表访问父类作用域下 cout << "Base 下 m_A = " << Son::Base::m_A << endl; } //同名成员函数 void test02() { //通过对象访问 cout << "通过对象访问: " << endl; Son s; s.func(); s.Base::func(); cout << "通过类名访问: " << endl; Son::func(); Son::Base::func(); //出现同名,子类会隐藏掉父类中所有同名成员函数,需要加作作用域访问 Son::Base::func(100); } int main() { //test01(); test02(); system("pause"); return 0; }
总结:
同名静态成员处理方式和非静态处理方式一样,只不过有两种访问的方式(通过对象 和 通过类名)
多继承语法
C++允许一个类继承多个类
语法:
class 子类 :继承方式 父类1 , 继承方式 父类2...
多继承可能会引发父类中有同名成员出现,需要加作用域区分
C++实际开发中不建议用多继承
示例:
class Base1 { public: Base1() { m_A = 100; } public: int m_A; }; class Base2 { public: Base2() { m_A = 200; //开始是m_B 不会出问题,但是改为mA就会出现不明确 } public: int m_A; }; //子类需要继承Base1和Base2 //语法:class 子类:继承方式 父类1 ,继承方式 父类2 … class Son : public Base2, public Base1 { public: Son() { m_C = 300; m_D = 400; } public: int m_C; int m_D; }; //多继承容易产生成员同名的情况 //通过使用类名作用域可以区分调用哪一个基类的成员 void test01() { Son s; //16 也可以使用开发者工具验证(前面已经说了) cout << "sizeof Son = " << sizeof(s) << endl; //当父类中出现同名成员,需要加作用域区分 cout << s.Base1::m_A << endl; cout << s.Base2::m_A << endl; } int main() { test01(); system("pause"); return 0; }
sizeof的结果:
总结:
多继承中如果父类中出现了同名情况,子类使用时候要加作用域
菱形继承(C++特色)
菱形继承概念:
两个派生类继承同一个基类
又有某个类同时继承者两个派生类
这种继承被称为菱形继承,或者钻石继承
菱形继承问题:
- 羊继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据时,就会产生二义性。
- 草泥马继承自动物的数据继承了两份,其实我们应该清楚,这份数据我们只需要一份就可以。
//动物类 class Animal { public: int m_Age; }; //利用虚继承,解决菱形继承问题。 //继承前加virtual关键字后,变为虚继承 //此时公共的父类Animal称为虚基类 class Sheep : virtual public Animal {}; //羊类 class Tuo : virtual public Animal {}; //驼类 class SheepTuo : public Sheep, public Tuo {}; //羊驼类 void test01() { SheepTuo st; st.Sheep::m_Age = 10; st.Tuo::m_Age = 20; //当出现菱形继承的时候,两个父类拥有系统数据,需要加以作用域区分 cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl; cout << "st.Tuo::m_Age = " << st.Tuo::m_Age << endl; //这份数据我们知道,只要有一份就行了,菱形继承导致数据有两份,资源浪费。 cout << "st.m_Age = " << st.m_Age << endl; } int main() { test01(); system("pause"); return 0; }
菱形继承的问题二:
加virtual虚继承之前:
利用虚继承,解决菱形继承的问题。
总结:
- 菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义
- 利用虚继承可以解决菱形继承问题
虚继承解决菱形继承问题的底层原理图解:
虚继承解决菱形继承问题的底层剖析 —— By CSDN码雨
结语:
博客制作不易,画图有点费眼,要是觉得博客对您有帮助,请一键三连嗷!
—— By CSDN码雨