C++ 继承与派生

本文详细介绍了C++中的继承与派生概念,包括派生类的声明、构造函数与析构函数、继承方式(公有、私有、保护)、多重继承、虚基类的使用以及基类与派生类之间的转换。重点讨论了继承的访问属性、构造函数执行顺序和如何避免二义性问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.继承和派生的概念

一个新类从已有的类中获得其属性和方法,这种现象称为类的 继承
从已有的类产生新的子类的现象,称为类的 派生
被继承的类称为 基类,派生的类称为 派生类或子类

派生类是抽象基类的实例。

2.派生类的声明

公用继承
class student1:public student

私有继承
class student1:private student

保护继承
class student1:protected student

注意:如果不写继承方式,则默认为私有(private)继承。

3.派生类的构成

派生类的构成包括:
(1)继承基类的所有成员,包括数据成员和成员函数,获得共性。全部继承(除构造函数和析构函数),没有选择,所以可能会造成基类方法在派生类中用不到,而导致大量冗余。
(2)自增加的成员,包括数据成员和成员函数。体现个性。

4.派生类成员的访问属性

(1)公用继承
继承方式指定为 public

在基类的访问属性继承方式在派生类的访问属性
publicpublicpublic
privatepublic不可访问
protectedpublicprotected

注意在公用派生类时,只能通过基类的公用成员函数来引用基类的私有数据成员

(2)私有继承
继承方式指定为 private

在基类的访问属性继承方式在派生类的访问属性
publicprivateprivate
privateprivate不可访问
protectedprivateprotected

注意既然声明为私有继承,就表示将原来能被外界引用的成员隐藏起来,不让外界引用。

(3)保护继承
继承方式指定为 protected
如果基类声明了私有成员,那么任何派生类都是不能访问它们的的;若希望派生类可以访问它们,应当把它们声明为保护成员

在基类的访问属性继承方式在派生类的访问属性
publicprotectedprotected
privateprotected不可访问
protectedprotectedprotected

注意基类中的保护成员只有派生类可以访问,友元可以访问基类的私有成员

保护成员和私有成员的区别在于把保护成员的范围扩展到派生类中

(4)多级派生访问属性
多级派生遵循单次派生的规则,依次叠加。
在实际中,常用多级公用派生。因为如果是私有派生或保护派生的话,多次派生之后,容易分不清楚哪些是私有、保护成员。

5.派生类的构造函数和析构函数

(1)派生类的构造函数
基类的构造函数是不能被继承的,故 在执行派生类的构造函数时,调用基类的构造函数,这样基类和派生类同时被初始化。

<1>在派生类 类体内 定义派生类构造函数:
    Student1(int n, string nam, char s, string con, string f_nam, int ag, string ad):Student(n, nam, s, con, f_nam)
    {
        age = ag;
        addr = ad;
    }

<2>在派生类 类体外 定义派生类构造函数:
//派生类类体中 声明:
Student1(int n, string nam, char s, string con, string f_nam, int ag, string ad); 

//派生类类体外 定义:
Student1::Student1(int n, string nam, char s, string con, string f_nam, int ag, string ad):Student(n, nam, s, con, f_nam)
    {
        age = ag;
        addr = ad;
    }

注意:在类中对派生类构造函数做声明时,不能包括基类的构造函数部分,只在定义时将它列出。
执行派生类构造函数顺序:基类->派生类

(2)有子对象的派生类的构造函数
在派生类Student1中,存在数据成员 Student monitor。此时,派生类构造函数需要加上子对象的初始化,基类和子对象的初始化顺序任意。编译系统依据相同参数名来确定它们的传递关系的

class Student1: public Student
{
public:

    Student1(int n, string nam, char s, string con, string f_nam, int n1, string nam1, char s1, string con1, string f_nam1, int ag, string ad):Student(n, nam, s, con, f_nam), monitor(n1, nam1, s1, con1, f_nam1)
    {
        age = ag;
        addr = ad;
    }

    void show();
    void show_monitor();

    ~Student1();

private:
    Student monitor;
    string addr;
    int age;
};

执行派生类构造函数顺序:基类->子对象->派生类

(3)多层派生的构造函数

class Student1: public Student
{
	Student1(...):Student(...)
	{ ... }
}

class Student2: public Student1
{
	Student2(...):Student1(...)
	{ ... }
}

注意不要列出每一层派生类的构造函数,只需写出其上一层(直接基类)的构造函数
执行派生类构造函数顺序:基类->派生类1->派生类2

(4)派生类构造函数特殊形式
<1>当不需要新增派生类的数据成员时,派生类的构造函数体可以为空;
<2>当基类的构造函数没有参数或没有定义时,定义派生类的构造函数时可以不写基类的构造函数。如果基类的构造函数有参数,则必须写。

(5)派生类的析构函数
调用顺序与调用构造函数相反。派生类->基类

6.多重继承

class D: public A, private B, protected C
{}

多重继承时,重名成员会导致二义性,因此对同名成员加上作用域("::")。多重继承也会导致数据冗余
注意:
<1>派生类新增的同名成员会 覆盖 基类中的同名成员;
<2>不同的成员函数,只有在函数名,参数个数和类型都相同时,才会发生 同名覆盖。如果只有函数名相同,则属于 函数重载

7.虚基类

(1)虚基类构建
如果一个派生类有多个直接基类,而这些基类又有一个共同的基类,则该派生类中会保留该间接共同基类的多份同名成员。
在这里插入图片描述
虚基类:在继承间接共同基类时只保留一份成员。

class A
{...};

class B:virtual public A
{...};

class C:virtual public A
{...};

注意
<1>虚基类在声明派生类、指定继承方式时声明的;
<2>派生类只继承间接基类一次,基类成员只保留一次;
<3>应当在基类的所有直接派生类中声明为虚基类,以保证虚基类在派生类中只继承一次。

(2)虚基类初始化

class A
{A(int n){} 
...};

class B:virtual public A
{B(int n):A(n){}
...};

class C:virtual public A
{C(int n):A(n){}
...};

class D:public B, public C
{D(int n):A(n), B(n), C(n){}
...};

注意最后的派生类不仅要对直接基类进行初始化,还要对虚基类进行初始化
C++编译系统只执行最后的派生类对虚基类的构造函数的调用,忽略其他派生类对虚基类构造函数的调用。

8.基类与派生类的转换

(1)派生类对象可以对基类对象赋值;
(2)派生类对象可以代替基类对象向基类对象的引用进行赋值或初始化;
(3)如果函数参数是基类对象或基类对象的引用,相应的实参可以用子类对象。
(4)指向基类对象的指针变量也可以指向派生类对象。通过指向基类对象的指针只能访问派生类中的基类成员,而不能访问派生类的增加成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值