目录

- class Person
- {
- public :
- void Print ()
- {
- cout<<_name <<endl;
- }
- protected :
- string _name = "Tom" ; // 姓名
- private :
- int _age ; // 年龄
- };
- //class Student : protected Person
- //class Student : private Person
- class Student : public Person
- {
- protected :
- int _stunum ; // 学号
- };
当我们使用public继承,我们发现父类的public访问限定符下Print()函数可以直接在类外使用

当我们使用protected和private继承,我们发现父类的public访问限定符下的Print()函数在类外无法再调用了

1. 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。2. 基类private成员在派生类中是不能被访问,如果 基类成员不想在类外直接被访问,但需要在派生类中能访问 ,就定义为protected。可以看出保护成员限定符是因继承才出现的。3. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public。
- class Person
- {
-
- protected:
- string _name; // 姓名
- string _sex; // 性别
- int _age; // 年龄
- };
- class Student : public Person
- {
- public:
- int _No; // 学号
- };
- void Test()
- {
- Student s;
- // 1.子类对象可以赋值给父类对象/指针/引用
- Person p = s;
- Person* pp = &s;
- Person& rp = s;
-
- //2.基类对象不能赋值给派生类对象
- s = p;
-
- }
-
- int main()
- {
- Test();
-
- return 0;
- }
- class A
- {
- public:
- void fun()
- {
- cout << "func()" << endl;
- }
- };
-
- class B : public A
- {
- public:
- void fun(int i)
- {
- //A::fun();
- cout << "func(int i)->" << i << endl;
- }
- };
-
- void Test()
- {
- B b;
- b.fun(10);//会调用谁的?
- };
-
- int main()
- {
- Test();
-
- return 0;
- }

我们发现调用的是子类的函数,这时因为 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义。那我们如何调用父类函数呢?可以在子类成员函数中,可以使用 基类::基类成员 显示访问。
多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承

- class Person
- {
- public:
- string _name; // 姓名
- };
- class Student : public Person
- {
- protected:
- int _num; //学号
- };
- class Teacher : public Person
- {
- protected:
- int _id; // 职工编号
- };
- class Assistant : public Student, public Teacher
- {
- protected:
- string _majorCourse; // 主修课程
- };
- void Test1()
- {
- cout << "Student的大小:" << sizeof(Student) << endl;
- cout << "Teacher的大小:" << sizeof(Teacher) << endl;
- cout << "Assistant的大小:" << sizeof(Assistant) << endl;
-
- 这样会有二义性无法明确知道访问的是哪一个
- //Assistant a;
- //a._name = "peter";
- 需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决
- //a.Student::_name = "xxx";
- //a.Teacher::_name = "yyy";
- }
- int main()
- {
- Test1();
-
- return 0;
- }

可以看出在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 Test ()
- {
- Assistant a ;
- a._name = "peter";
- }
- class A
- {
- public:
- int _a;
- };
-
- class B : virtual public A
- {
- public:
- int _b;
- };
-
- class C : virtual public A
- {
- public:
- int _c;
- };
-
- class D : public B, public C
- {
- public:
- int _d;
- };
- int main()
- {
- D d;
- d.B::_a = 1;
- d.C::_a = 2;
- d._b = 3;
- d._c = 4;
- d._d = 5;
- return 0;
- }

我们不使用虚拟继承可以看到数据冗余
我们使用虚拟继承来看看

