C++——菱形继承、虚继承

继承

一.含义

继承来自父类的成员(数据成员和成员函数)

二.访问规则:

父类成员变量在子类中的访问权限:在父类中的原有权限和继承方式中取最小即可。

min(父类中的原有权限,继承方式)

三.切片操作

子类为父类赋值(对象、引用、指针)

父类不能为子类赋值,除非强制类型转换,但是这样操作的结果就是会出现,访问到非法内存的情况。

四.菱形继承

1.菱形继承的结构如下:

 代码表示如下:

//菱形继承
class A {
public:
	int a;
};

class B1 :public A {
public:
	int b1;
};

class B2 :public A{
public:
	int b2;
};

class C :public B1, public B2 {
public:
	int c;
};

但是,这样会出现数据冗余,与二义性的问题。

数据冗余:C的两个直接父类都存储了根本父类A的数据元素

二义性:通过继承关系,A的数据成员被继承了两份,通过C来访问其继承的A的数据元素时,会出现二义性,不清楚是B1继承的还是B2继承的。

看下面的代码:

void test2() {
	C c;
	c.B1::a = 40;
	c.B2::a = 50;
	c.b1 = 2;
	c.b2 = 3;
	c.c = 9;
}

当我们想修改C中继承的A的成员的值时,会出现二义性,修改一次后我们希望得到的结果应该是C继承体系中的a变量的值均被修改并且相同,但是呈现的结果却是这样的:

为了解决菱形继承的数据冗余和二义性的问题,我们引入虚拟继承来解决。

//菱形继承
class A {
public:
	int a;
};

class B1 :virtual public A {
public:
	int b1;
};

class B2 :virtual public A{
public:
	int b2;
};

class C :public B1, public B2 {
public:
	int c;
};

这样处理的结果是:

两种实现的原理:

 这样看似空间比原来占用还大,但事实上,当根本父类A的成员变量多的时候,虚拟继承就体现出了它的空间优势。

五.派生类的默认成员函数:

class Person {
private:
	int age;
public:
	Person() {
		cout << "Person()" << endl;
	}

	~Person() {
		cout << "~Person()" << endl;
	}
};

class Student :public Person {
private:
	int sno;
public:
	Student() {
		cout << "Student()" << endl;
	}

	~Student() {
		cout << "~Student()" << endl;
	}
};

class Teacher :public Person {
private:
	int tno;
public:
	Teacher() {
		cout << "Teacher()" << endl;
	}
	~Teacher() {
		cout << "~Teacher()" << endl;
	}
};

void test1() {
    	Person p;
	Student s;
	Teacher t;
}

函数调用情况如下:

构造与析构:派生类默认先调基类的构造函数,析构函数,先调用派生类的析构函数,再调用基类的析构函数。

拷贝构造:派生类有显示的拷贝构造,优先调用派生类的,不再调用基类的;否则,就自动调用基类的拷贝构造。

赋值运算符重载:调用规则与构造函数一致。

六.继承中的静态成员

当基类定义了一个静态成员时,该静态成员属于整个继承体系——它的任何一个派生类。

发布了58 篇原创文章 · 获赞 43 · 访问量 4405

猜你喜欢

转载自blog.csdn.net/Wz_still_shuai/article/details/94408439
今日推荐