栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

解决 C++ 多继承中的菱形问题

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

解决 C++ 多继承中的菱形问题

先看代码:

#include
using namespace std;
class Person // 基类
{

protected:  
   int age;
};
class Student : public Person // 派生类
{

};

class Teacher: public Person // 派生类
{

};

class AssiTeacher : public Student, public Teacher // 最远派生类
{

};

int main()
{
  AssiTeacher a;
  a.age = 25;
}

菱形问题对这个例子来说就是:你想要通过AssiStudent实例访问Person::age,将导致编译错误。

a.age 是模糊的(ambigous),因为编译器不知道你是要问:Student::Person::age 还是Teacher::Person::age,造成了二义性。
如果你愿意,你甚至可以分别设置他们:

Student::Person::var  =25;
Teacher::Person::a = 26;

这显然是不合理的,因为助教AssiTeacher显然只需要一个age属性

为什么会造成这样的问题?我们来看创建对象a时,对各个类的构造过程:
我们可以看到,按基类先构造原则,编译器通过分别调用Teacher和Student的构造函数,将Person类构造了两次,造成了重复。我们知道,在编程中,只要出现了重复那必然伴随着错误。要避免错误,我们就要消除掉对Person类的重复构造。

如果派生类可能被用作基类,为了防止出现二义性,在派生类derive从基类Base继承时 选择虚继承。

若派生类Derive 不作基类使用,最好加上 final禁止继承

注意看代码注释

#include
#include
using namespace std;


class Person
{
public:
	Person(string inName, int inAge):name(inName),age(inAge)
	{
		cout << "construct Person" << endl;
	}
	void display()
	{
		cout << name <
public:
	Student(string inName, int inAge,string inId,string inScore):Person(inName,inAge),id(inId),score(inScore)
		// 这里不会执行Person基类的构造函数
	{
		cout << "construct Student" << endl;
	}

	void display()
	{
		Person::display();
		cout << id << endl;
		cout << score << endl;
	}


protected:
	string id, score;
};

class Teacher : virtual public Person //虚基类,避免对基类的重复构造引发菱形问题
{
public:
	Teacher(string inName, int inAge,string inDepart,float inSalary):Person(inName, inAge),department(inDepart),salary(inSalary)
		// 这里不会执行Person基类的构造函数
	{
		cout << "construct Teacher" << endl;
	}
	void display()
	{
		Person::display();
		cout << department << endl;
		cout << salary << endl;
	}

private:
	string department;
	float salary;
};

class AssiTeacher final:public Teacher, public Student  // 最派生类
{
public:
	AssiTeacher(string inName, int inAge, string inId, string inScore,string inDepart, float inSalary)
		:Person(inName,inAge),  Student(inName, inAge, inId , inScore), Teacher(inName, inAge, inDepart, inSalary)
		//在最派生类(AssiTeacher)中不仅要对直接基类进行初始化,还要负责对虚基类初始化。
		// 在这里构造Person,Student,Teacher
	{
		cout << "constructed AssiTeacher" << endl;
	}
	
	void display()
	{
		Teacher::display();
		Student::display();
	}
};

int main()
{
	AssiTeacher a("通辽可汗", 25, "20220427", "97", "teacher", 3000.0);
	a.display();

	return 0;
}

此时的构造顺序为:至此,解决了重复构造Person类的问题,菱形问题解决

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/853103.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号