【C/C++】【类和对象】多重继承和虚继承

2021-04-10 23:30

阅读:437

标签:std   其他   不能   通过   定义   value   类构造   成员   移动   

继承的构造函数

  • 一个类只继承其直接基类的构造函数,默认/拷贝/移动构造函数是不能被继承的;

  • 继承Father的构造函数

    using Father::Father; 
    //继承Father的构造函数 using让某个名字在当前的作用域可见;
    //编译器遇到这条代码的时候,会把基类的每个构造函数都生成一个与之对应的派生类构造函数
    
  • 如果基类A的构造函数有默认参数的话,那么编译器遇到这种using A::A的时候,就会帮咱们在派生类B中构造出多个构造函数来;

    1. 第一个构造函数时带有所有参数的构造函数;
    2. 其余的构造函数,每个分别省略掉一个默认参数;
    //示例:
    Son(int i, int j, int k = 5) :Father(i, j, k){};
    Son(int i, int j, int k):Father(i,j,k){};
    Son(int i, int j):Father(i,j){};
    
  • 如果基类含多个构造函数,则多数情况下,派生类会继承所有这些构造函数,但如下情况例外:

    1. 如果在派生类中定义的构造函数与基类构造函数有相同的参数列表,那么从基类中继承来的构造函数会被你在派生类中定义的覆盖掉,相当于只继承了一部分构造函数;
    2. 默认/拷贝/移动构造函数是不会被继承的;
    3. 如果子类,只含有using Father::Father从Father继承来的构造函数的话,那么编译器会给它合成默认的构造函数;
#include 
using namespace std;

class Father
{
public:
	Father(int i, int j, int k)
	{

	}
};

class Son : public Father
{
public:
	using Father::Father; //继承Father的构造函数 using让某个名字在当前的作用域可见;
	//编译器遇到这条代码的时候,会把基类的每个构造函数都生成一个与之对应的派生类构造函数

};

int main()
{
	Son son(3, 4, 5);
}

多重继承

从多个父类产生出子类,多重继承;

多重继承概述

#include 
using namespace std;

class Base
{
public:
	Base(int i) :m_value_base(i) {};
public:
	int m_value_base;

	virtual ~Base()
	{

	}

	void my_info()
	{
		cout 

静态成员变量

静态成员属于类,不属于对象;

为了能够使用,需要定义静态成员变量;如果代码中不用该静态变量,可以不定义;如果用到该静态变量,可以定义;否则,链接出错;

#include 
using namespace std;

class Base
{
public:
	Base(int i) :m_value_base(i) {};
public:

	virtual ~Base()
	{

	}

	void my_info()
	{
		cout 

派生类构造函数和析构函数

  1. 构造一个派生类对象将同时构造并初始化所有基类子对象;
  2. 派生类的构造函数初始化列表只初始化它的直接基类,每个类的构造函数都负责初始化它的直接基类,就会让所有类都初始化;
  3. 派生类构造函数初始化列表将实参分别传递给每个直接基类;基类的构造顺序跟派生列表(继承的顺序 )中基类的出现顺序保持一致;
  4. 析构函数的调用顺序与构造函数的顺序完全相反;

显示的初始化基类和隐式的初始化基类

  • 隐式的初始化基类: 派生类的构造函数初始化列表中没有调用带参数的基类构造函数,而是调用的基类的默认构造函数来实现基类的初始化;
#include 
using namespace std;

class Base
{
public:
	Base(int i) :m_value_base(i) 
	{
		cout 

从多个父类继承构造函数

如果一个类从它的基类中继承了相同的构造函数,这个类必须为该构造函数定义它的自己的版本;
子类要定义同参数的构造函数的自己的版本;

#include 
using namespace std;

class Father_A
{
public:
	Father_A(int tv) {};
};
class Father_B
{
public:
	Father_B(int tv) {};
};

class Son :public Father_A, public Father_B
{
	using Father_A::Father_A;//继承Father_A的构造函数   Son(int tv):Father_A(tv){}
	using Father_B::Father_B;//继承Father_B的构造函数   Son(int tv):Father_B(tv){}
	
    Son(int tv) :Father_A(tv), Father_B(tv) {};

};

int main()
{

}

类型转换

基类指针可以指向一个派生类对象:编译器隐式执行这种派生类到基类的转换,转换成功的原因是每个派生类对象都包含一个基类对象部分;所以基类的引用或者指针是可以绑定到基类对象这部分;

上述对于多重继承同样成立;

#include 
using namespace std;

class Base
{
public:
	Base(int i) :m_value_base(i) 
	{
		cout 

虚基类,虚继承

派生列表中,同一个基类只能出现一次,但是如下两种情况例外;

  1. 派生类可以通过它的两个直接基类分别继承同一个间接基类;

  2. 直接继承某个基类,然后通过另一个基类间接继承

虚基类和虚继承

  • 无论这个类在继承体系中出现多少次,派生类中,都只会包含唯一一个共享的虚基类字内容;不会出现访问不明确的问题;
  • 虚继承只是对孙子类有意义,对孙子类的直接基类没有意义;例Son继承Father_A和Father_C,Father_A和Father_C继承Base;那么Father_A和Father_B虚继承Base,对Son有意义,避免它间接继承Base两次;
  • 虚继承:表示后续从本类派生的类应该共享虚基类Base的同一份实例;
  • 虚继承之后:虚基类的初始化使用孙子类;

说明

  • 现在是Son类初始化虚基类,如果Son有了子类,那么由Son的子类初始化虚基类;虚基类是由最底层的派生类来初始化;
  • 初始化顺序:先初始化虚基类,然后按照派生列表中出现的顺序来初始化其他类;多个虚基类的话,按照派生列表中直接基类往回追溯,看是否这些直接基类中是否含有虚基类,反正是先追溯到哪个,先构造那个虚基类;析构顺序和构造顺序相反;
#include 
using namespace std;

class Base
{
public:
	Base(){}
	Base(int i) :m_value_base(i) 
	{
		cout 

总结

  • 不太提倡使用多重继承;简单,不容易出现二义性,使用多重继承;
  • 使用单一继承能解决的尽量不要用多重继承;

【C/C++】【类和对象】多重继承和虚继承

标签:std   其他   不能   通过   定义   value   类构造   成员   移动   

原文地址:https://www.cnblogs.com/Trevo/p/13363941.html


评论


亲,登录后才可以留言!