此篇文章将详细的讲解继承的作用和使用方法。
一个类,继承另一个已有的类,创建的过程
父类(基类)派生出子类(派生类)的过程
继承提高了代码的复用性
- class 类名:父类名
- {};
- class 类名:继承的权限 父类名
- {};
-
- 如果不写继承方式,默认是私有继承
- 父类中的权限 public|private|protected public|private|protected public|private|protected
- 继承方式 public private protected
- 子类中的权限 public|不能访问|protected private|不能访问|private protected|不能访问|protected
特殊的成员函数不会被继承
构造函数:
需要在子类中显性调用父类构造函数的场合:
父类中只有有参构造 ----->子类在创建类对象时,必须手动调用父类的构造函数
- #include <iostream>
-
- using namespace std;
-
- class Father
- {
- public:
- int age;
- char c;
- Father(int a,char c):age(a),c(c){cout << "Father有参" << endl;}
- };
-
- class Child:public Father //----->私有继承
- {
- int high;
- public:
- void show()
- {
- cout << c << endl;
- }
- };
-
- int main()
- {
- //Child c1; //error,因为父类只有有参构造,而子类中没有提供能够调用父类有参构造的构造函数,不能成功创建父类的空间
- //Father f1;
- c1.age;
- cout << sizeof (Father) << endl;
- cout << sizeof (Child) << endl;
- return 0;
- }
在子类构造函数的初始化列表中,显性调用父类的构造函数

C++支持
不用在子类中再写一遍父类的构造函数
使用:using Father::Father; ----->在子类中使用父类的构造函数
直接使用继承构造的方式,不能对子类成员初始化
继承构造本质上并不是把父类中的构造函数继承给子类,编译器自动根据父类中构造函数的格式,提供出派生的构造函数(个数和参数都和父类中的构造函数一致),主要还是通过透传构造创建父类的空间

- #include <iostream>
- using namespace std;
-
- class Father
- {
- public:
- int age;
- char c;
- // Father(){cout << "Father无参" << endl;}
- Father(int a,char c):age(a),c(c){cout << "Father有参两个参数" << endl;}
- Father(char c):c(c){cout << "Father有参一个参数的" << endl;}
- Father(Father &other):age(other.age),c(other.c)
- {cout << "Father拷贝" << endl;}
- };
-
- class Child:public Father //----->私有继承
- {
- private:
- int high;
- //父类中的public成员age,通过公有继承,仍然是public
- using Father::age; //把父类中公有继承下来的age成员,在子类中改成私有权限
- public:
- void show()
- {
- cout << c << endl;
- }
- //子类的无参构造,但是显性调用父类的有参构造还给了默认值
- //透传构造
- // Child():Father(12,'a'){cout << "Child无参构造" << endl;}
- // Child(int a,char c,int h):Father(a,c),high(h)
- // {cout << "Child有参构造" << endl;}
-
- //父类中的所有构造函数,都被继承到了子类中
- using Father::Father; //更高效一些
- };
-
- int main()
- {
- Child c1(10);
- Child c2(20,'z');
- Child c3 = c2;
- //Father f1;
- //c1.age;
- cout << sizeof (Father) << endl;
- cout << sizeof (Child) << endl;
- return 0;
- }
一个类的情况,并不直接通过无参构造实例化对象,而是无参构造委托了有参构造,实例化对象

继承时的情况

- Child():Child(10){cout << "Child无参构造" << endl;} //Child c1
- Child(int a):Father(12,'a'),high(a)
- {cout << "Child有参构造一个参数" << endl;}
需要在初始化列表中显性调用父类的拷贝构造,传other对象到父类的拷贝构造中
- Father(Father &other):age(other.age),c(other.c){cout << "Father的拷贝构造" << endl;}
- Child(Child &other):Father(other),high(other.high){}
继承关系,可以理解为包含关系
子类在继承父类时,会把父类中的成员保留一份,再来创建子类自己的成员
父类先构造,子类后构造
子类先析构,父类后析构
- #include <iostream>
-
- using namespace std;
- class F
- {
- int *p;
- public:
- F():p(new int){cout << "F无参构造" << endl;}
- ~F()
- {
- delete p;
- cout << "F析构函数" << endl;
- }
- };
- class C:public F
- {
- int *p;
- public:
- C():p(new int){cout << "C无参构造" << endl;}
- ~C()
- {
- delete p;
- cout << "C析构函数" << endl;
- }
- };
-
- int main()
- {
- C *p1 = new C;
- delete p1; //空间释放时,会自动调用析构函数,无需手动调用
- p1 = nullptr;
- return 0;
- }

访问时不会发生冲突,默认访问子类的
- #include <iostream>
- using namespace std;
- class F
- {
- public:
- int *p;
- F():p(new int){cout << "F无参构造" << endl;}
- ~F()
- {
- delete p;
- cout << "F析构函数" << endl;
- }
- };
- class C:public F
- {
- public:
- int *p;
- C():p(new int){cout << "C无参构造" << endl;}
- ~C()
- {
- delete p;
- cout << "C析构函数" << endl;
- }
- };
-
- int main()
- {
- C *p1 = new C;
- *(p1->p) = 90;
- cout << *(p1->p) << endl; //子类成员和父类成员同名,默认优先访问子类成员
- cout << *(p1->F::p) << endl; //通过域限定符访问父类的成员
- delete p1; //空间释放时,会自动调用析构函数,无需手动调用
- p1 = nullptr;
- return 0;
- }
一个子类,继承自多个基类
- class 类名:继承权限 父类名,继承权限 父类名····
- {}
多个父类中包含同名成员,通过域限定符访问指定的父类中成员
- #include <iostream>
-
- using namespace std;
-
- class Room
- {
- public:
- void clean()
- {
- cout << "打扫房间" << endl;
- }
- };
- class BedRoom
- {
- public:
- void play()
- {
- cout << "可以玩游戏" << endl;
- }
- void clean()
- {
- cout << "打扫卧室" << endl;
- }
- };
-
- //Home类公共继承字Room和BedRoom类
- class Home:public Room,public BedRoom
- {
- };
-
- int main()
- {
- Home h1;
- h1.play();
- h1.Room::clean();
- h1.BedRoom::clean();
- return 0;
- }
- A ----->公共基类
- / \
- B C ------>中间子类
- \ /
- D ------>汇集子类
汇集子类中,会包含两份公共基类中的内容
- #include <iostream>
-
- using namespace std;
- class A
- {
- public:
- int a;
- //A(int a):a(a){cout << "A" << endl;}
- };
-
- class B:public A
- {
- public:
- int c;
- //B(int a,int c):A(a),c(c){cout << "B" << endl;}
- };
-
- class C:public A
- {
- public:
- //C(int a):A(a){cout << "C" << endl;}
- };
-
- class D:public C,public B
- {
- public:
- //D(int a,int c):B(a,c),C(a),A(a){cout << "D" << endl;}
- };
-
- int main()
- {
- D d1;
- d1.B::a = 90; //二义性,还可以直接通过中间子类访问,直接访问B中的a成员
- //cout << d1.C::A::a << endl; //会发生二义性,因为访问A,但是有两条路径都访问到A
- return 0;
- }
虚继承指对公共基类的虚继承。
主要用于解决菱形继承问题,
采用虚继承后,公共基类中的内容,只会在汇集子类中存在一份,在汇集子类中,可以通过任意一条路径访问到公共基类中的成员
- #include
-
- using namespace std;
- class A
- {
- public:
- int a;
- };
-
- class B:virtual public A
- {
- public:
- int c;
- };
-
- class C:virtual public A
- {
-
- };
-
- class D:public B,public C
- {
-
- };
-
- int main()
- {
- D d1;
- d1.B::A::a = 90;
- cout << d1.C::A::a << endl;
- return 0;
- }