uacs2024

导航

C++ 继承

 1 // 基类
 2 class Animal {
 3     // eat() 函数
 4     // sleep() 函数
 5 };
 6 
 7 
 8 //派生类
 9 class Dog : public Animal {
10     // bark() 函数
11 };

基类 & 派生类

一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:

class derived-class: access-specifier base-class

其中,访问修饰符 access-specifier 是 public、protected 或 private 其中的一个,base-class 是之前定义过的某个类的名称。如果未使用访问修饰符 access-specifier,则默认为 private

访问控制和继承

派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。

我们可以根据访问权限总结出不同的访问类型,如下所示:

访问publicprotectedprivate
同一个类 yes yes yes
派生类 yes yes no
外部的类 yes no no

一个派生类继承了所有的基类方法,但下列情况除外:

  • 基类的构造函数、析构函数和拷贝构造函数。
  • 基类的重载运算符。
  • 基类的友元函数。

多继承

多继承即一个子类可以有多个父类,它继承了多个父类的特性。

C++ 类可以从多个类继承成员,语法如下:

class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
};

其中,访问修饰符继承方式是 public、protected 或 private 其中的一个,用来修饰每个基类,各个基类之间用逗号分隔,如上所示。

菱形继承

多继承(环状继承),A->D, B->D, C->(A,B)

class D{......};
class B: public D{......};
class A: public D{......};
class C: public B, public A{.....};

这个继承会使D创建两个对象,要解决上面问题就要用虚拟继承格式

格式:class 类名: virtual 继承方式 父类名

class D{......};
class B: virtual public D{......};
class A: virtual public D{......};
class C: public B, public A{.....};

虚继承--(在创建对象的时候会创建一个虚表)在创建父类对象的时候

A:virtual public D
B:virtual public D
 1 #include <iostream>
 2 
 3 using namespace std;
 4 //基类
 5 
 6 class D
 7 {
 8 public:
 9     D(){cout<<"D()"<<endl;}
10     ~D(){cout<<"~D()"<<endl;}
11 protected:
12     int d;
13 };
14 
15 class B:virtual public D
16 {
17 public:
18     B(){cout<<"B()"<<endl;}
19     ~B(){cout<<"~B()"<<endl;}
20 protected:
21     int b;
22 };
23 
24 class A:virtual public D
25 {
26 public:
27     A(){cout<<"A()"<<endl;}
28     ~A(){cout<<"~A()"<<endl;}
29 protected:
30     int a;
31 };
32 
33 class C:public B, public A
34 {
35 public:
36     C(){cout<<"C()"<<endl;}
37     ~C(){cout<<"~C()"<<endl;}
38 protected:
39     int c;
40 };
41 
42 int main()
43 {
44     cout << "Hello World!" << endl;
45     C c;   //D, B, A ,C
46     cout<<sizeof(c)<<endl;
47     return 0;
48 }

结果

Hello World!
D()
B()
A()
C()
40
~C()
~A()
~B()
~D()

为什么子类的构造函数中会出现在初始化列表中呢?原因在于子类能够从基类继承的内容限制上。

我们知道,一个派生类继承了所有的基类方法,但下列情况除外:

  • 基类的构造函数、析构函数和拷贝构造函数。
  • 基类的重载运算符。
  • 基类的友元函数。

因此,我们不能够在子类的成员函数体中调用基类的构造函数来为成员变量进行初始化。例如这样子是不可以的

 1 #include <iostream>
 2  
 3 using namespace std;
 4  
 5 // 基类
 6 class Shape 
 7 {
 8    public:
 9       Shape(int w,int h)
10       {
11         width=w;
12         height=h;
13       }
14    protected:
15       int width;
16       int height;
17 };
18  
19 // 派生类
20 class Rectangle: public Shape
21 {
22    public:
23       Rectangle(int a,int b)
24       {
25         Shape(a,b);   //错误的
26       }
27 
28      
29 };

但我们可以把基类的构造函数放在子类构造函数的初始化列表上,以此实现调用基类的构造函数来为子类从基类继承的成员变量初始化。

 1 #include <iostream>
 2 using namespace std;
 3 // 基类
 4 class Shape 
 5 {
 6    public:
 7       Shape(int w,int h)
 8       {
 9         width=w;
10         height=h;
11       }
12    protected:
13       int width;
14       int height;
15 };
16 // 派生类
17 class Rectangle: public Shape
18 {
19    public:
20       Rectangle(int a,int b):Shape(a,b)
21       {        
22       }
23 };

 

posted on 2024-03-02 18:02  ᶜʸᵃⁿ  阅读(2)  评论(0编辑  收藏  举报