首页 > 编程语言 >C++ 继承

C++ 继承

时间:2024-03-02 18:12:22浏览次数:24  
标签:继承 C++ class int 基类 public 构造函数

 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 };

 

标签:继承,C++,class,int,基类,public,构造函数
From: https://www.cnblogs.com/uacs2024/p/18048998

相关文章

  • C++ 类的静态成员
    原文可以使用 static 关键字来把类成员定义为静态的。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。我们不能把静态......
  • C++ 指向类的指针
    原文一个指向C++类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符 ->,就像访问指向结构的指针一样。与所有的指针一样,在使用指针之前,对指针进行初始化。在C++中,指向类的指针指向一个类的对象,与普通的指针相似,指向类的指针可以用于访问对象的成员......
  • C++ 拷贝构造函数(初学有点难理解)
    拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:通过使用另一个同类型的对象来初始化新创建的对象。复制对象把它作为参数传递给函数。复制对象,并从函数返回这个对象。如果在类中没有定义拷......
  • C++填坑系列——新手写代码易错点
    c++新手写代码的几个易错点学习自https://www.youtube.com/watch?v=i_wDa2AS_8w1.限制usingnamespacestd的作用范围如果你自己定义了一个和std空间内同名的函数,当你把std放到globalnamespace(也就是直接usingnamespacestd)中,就会出现函数冲突;usingnamespacestd的使......
  • C++填坑系列——万能引用+移动语义+完美转发
    模板编程中的万能引用、移动语义、完美转发万能引用:T&&,辅助模板编程,这样左值和右值的参数都可以接收;移动语义:std::move,转换为右值,也可结合移动构造函数和移动赋值使用;完美转发:std::forward,可以保留参数的左值和右值属性,因为后续使用该参数可能还需要这个属性;万能引用万能引......
  • C++填坑系列——EffectiveModernC++之类型推导
    接下来会记录我在学习《EffectiveModernC++》的一些总结和思考。鉴于C++的知识太多了,我难以全面覆盖到学习,所以这里借此来补充和发散自己的学习心得:)以下内容由学习这个网站EffectiveModernC++的中文翻译内容得来https://cntransgroup.github.io/EffectiveModernCppChine......
  • C++填坑系列——EffectiveModernC++之新手怎么进入现代C++
    新手怎么进入现代C++1.使用auto来自动推导变量类型2.使用{}来创建变量和对象3.使用nullptr来创建空指针4.使用using代替typedef进行别名定义5.使用enumclass代替enum进行枚举定义6.使用=delete来禁止调用一个函数7.使用override来修饰继承链中的重写函数8.使用co......
  • C++填坑系列——EffectiveModernC++之特殊成员函数
    Chapter移步现代c++之特殊成员函数Item17:Understandspecialmemberfunctiongeneration总结:有必要了解各个函数什么时候自动生成;自动生成的函数有可能产生预期外的行为;特殊成员函数(编译器自动生成):默认构造函数,析构函数,拷贝构造函数,拷贝赋值运算符,移动构造函数,移动赋......
  • C++ 多线程笔记2 线程同步
    C++多线程笔记2线程同步并发(Concurrency)和并行(Parallelism)并发是指在单核CPU上,通过时间片轮转的方式,让多个任务看起来像是同时进行的。实际上,CPU在一个时间段内只会处理一个任务,但是由于切换时间非常快,用户感觉像是多个任务同时在进行。这种方式的优点是可以充分利用CPU资源,......
  • C#的类和对象,继承
    ///类与对象///类和对象是面向编程的两个核心概念///类:类是对一群具有相同特征的或者行为事物的统称类是图纸///对象是由类创造出来的一个具体存在可以直接使用对象是图纸造出来的汽车///现有类再有对象类是抽象的对象是具体的//////类的设计数据建模//......