C++ 继承(2): 多重继承, 多继承, 虚继承(virtual)

C++远征之继承篇 视频教程 笔记 方便自己查阅和复习,温故而知新。

接着  C++ 继承(1): 继承方式(public, protected, private), 继承中的特殊关系(隐藏 , is-a) 继续做笔记

 

目录

4 多继承与多重继承

4.1  多重继承

4.2  多继承

代码示例

5 虚继承

代码示例

参考资料


 

 

4 多继承与多重继承

4.1  多重继承

如下图示,士兵类 继承 人类 , 步兵类 继承 士兵类。我们称之为 这三者 属于 多重继承关系

 

我们还可以知道 这三者 相互之间 是 is-a 关系

 

在代码中 可以写为:

 

 

 

4.2  多继承

一个类有两个及以上的父类,称之为 多继承。注意区别前面的 多重继承

 

 

在代码中 形式为:

 

 

代码示例

示例1:多重继承
要求:
1 定义Person类
    数据成员: m_strName 
    成员函数:构造函数  析构函数 play()

2 定义Soldier类:
    数据成员: m_iAge
    成员函数:构造函数  析构函数  worker()

3 定义Infantry类 
    数据成员:无
    成员函数: 构造函数 attack()

4 定义函数test1(Person p) test2(person &p) test3(Person *p)

//Person.h
#pragma once
#include<iostream>
#include<string>
using namespace std;

class Person
{
public:
	Person(string name="pesrson_001");//构造函数
	virtual ~Person();// virtual 防止内存泄漏

	void play();

protected:
	string m_strName;

};
//Person.cpp

#include<iostream>
#include"Person.h"
using namespace std;


Person::Person(string name)
{
	m_strName = name;
	cout << "Person()--构造" << endl;
}

Person::~Person()
{
	cout << "~Person()--析构" << endl;
}

void Person::play()
{
	cout << "Name: " << m_strName << endl;
	cout << "Person--play()" << endl;
}

 

//Soldier.h

#pragma once
#include<iostream>
#include"Person.h"

class Soldier:public Person
{
public:
	Soldier(string name = "soldier_001", int age = 20);
	virtual ~Soldier();//virtual 防止内存泄漏
	void work();

protected:
	int m_iAge;
};
//Soldier.cpp

#include<iostream>
#include"Soldier.h"
using namespace std;
Soldier::Soldier(string name, int age)
{
	m_strName = name;
	m_iAge = age;
	cout << "Soldier()--构造" << endl;
}

Soldier::~Soldier()
{
	cout << "~Soldier()--析构" << endl;
}

void Soldier::work()
{
	cout << "Name= "<< m_strName << endl;
	cout << "Age= " << m_iAge << endl;
	cout << "Soldier--work()" << endl;
}

 

//Infantry.h
#pragma once
#include"Soldier.h"

class Infantry:public Soldier
{
public:
	Infantry(string name = "Infantry_001", int age = 18);
	~Infantry();

	void attack();
};
//Infantry.cpp
#include"Soldier.h"
#include"Infantry.h"
Infantry::Infantry(string name, int age)
{
	m_strName = name;
	m_iAge = age;
	cout << "Infantry()--构造" << endl;
}

Infantry::~Infantry()
{
	cout << "~Infantry()--析构" << endl;
}

void Infantry::attack()
{
	cout << "Name= " << m_strName << endl;
	cout << "Age= " << m_iAge << endl;
	cout << "Infantry--attack()" << endl;
}

 

 

//main.cpp

#include<iostream>
#include"Infantry.h"
using namespace std;
/*************************
多重继承
要求:
1 定义Person类
	数据成员: m_strName 
	成员函数:构造函数  析构函数 play()

2 定义Soldier类:
	数据成员: m_iAge
	成员函数:构造函数  析构函数  worker()

3 定义Infantry类 
	数据成员:无
	成员函数: 构造函数 attack()

4 定义函数test1(Person p) test2(person &p) test3(Person *p)
**************************/
void test1(Person p)
{
	p.play();
}

void test2(Person &p)
{
	p.play();
}

void test3(Person *p)
{
	p->play();
}



int main()
{
	Infantry infantry;
	cout << "---------- 1 -----------" << endl;
	
	test1(infantry); //产生新的临时对象,函数调用后 自动销毁(调用析构函数)

	cout << "" << endl;
	cout << "---------- 2 -----------" << endl;
	cout << "" << endl;

	test2(infantry);

	cout << "" << endl; //没有产生新的临时对象
	cout << "---------- 3 -----------" << endl;
	cout << "" << endl;

	test3(&infantry); //没有产生新的临时对象


	cin.get();
	return 0;
}

运行结果:

 

 

示例2: 多继承

要求:多继承
1 定义Farmer类
    数据成员: m_strName 
    成员函数:构造函数  析构函数 sow()

2 定义Worker类:
    数据成员: m_strCode
    成员函数:构造函数  析构函数  carry()

3 定义MigrantWorker类 
    数据成员:无
    成员函数: 构造函数 析构函数

//Worker.h

#pragma once
#include<iostream>
#include <string>
using namespace std;
class Worker
{
public:
	Worker(string code="Worker_001");
	virtual ~Worker();

	void carry();

protected:
	string m_strCode;
};
//Worker.cpp

#include<iostream>
#include"Worker.h"
using namespace std;

Worker::Worker(string code)
{
	m_strCode = code;
	cout << "Worker()--构造" << endl;
}

Worker::~Worker()
{
	cout << "~Worker()--析构" << endl;
}

void Worker::carry()
{
	cout << "Code= " << m_strCode << endl;
	cout << "Worker--carry()" << endl;
}

 

//Farmer.h

#pragma once
#include<iostream>
#include <string>
using namespace std;
class Farmer
{
public:
	Farmer(string name = "Farmer_001");
	virtual ~Farmer();

	void sow();

protected:
	string m_strName;
};
//Farmer.cpp
#include"Farmer.h"
using namespace std;

Farmer::Farmer(string name)
{
	m_strName = name;
	cout << "Farmer()--构造" << endl;
}

Farmer::~Farmer()
{
	cout << "~Farmer()--析构" << endl;
}

void Farmer::sow()
{
	cout << "Name= " << m_strName << endl;
	cout << "Farmer()--sow()" << endl;
}

 

//MigrantWorker.h
#pragma once
#include<iostream>
#include <string>
using namespace std;

#include"Worker.h"
#include"Farmer.h"

class MigrantWorker:public Worker, public Farmer //继承两个类
{
public:
	MigrantWorker(string name, string code);
	~MigrantWorker();
};
//MigrantWorker.cpp

#include"MigrantWorker.h"
using namespace std;
MigrantWorker::MigrantWorker(string name, string code):Farmer(name),Worker(code)
{
	cout << "MigrantWorker()--构造" << endl;
}


MigrantWorker::~MigrantWorker()
{
	cout << "~MigrantWorker()--析构" << endl;
}

 

//main.cpp

#include<iostream>
#include"MigrantWorker.h"
using namespace std;
/*************************
多继承
要求:
1 定义Farmer类
	数据成员: m_strName 
	成员函数:构造函数  析构函数 sow()

2 定义Worker类:
	数据成员: m_strCode
	成员函数:构造函数  析构函数  carry()

3 定义MigrantWorker类 
	数据成员:无
	成员函数: 构造函数 析构函数
**************************/

int main()
{
	MigrantWorker *p = new MigrantWorker("HAHA","002");
	cout << "---------- 1 -----------" << endl;
	cout << "" << endl;

	p->carry();
	p->sow();
	cout << "---------- 2 -----------" << endl;
	cout << "" << endl;

	delete p;
	p = NULL;


	cin.get();
	return 0;
}

 

运行结果:

 

 

 

 

5 虚继承

 

 

上面的这种继承属于菱形继承如果实例化对象D 那么D—>B—>A  D—>C—>A , 此时D将会从A得到两个相同的数据,这属于数据冗余,是不能容忍的。

 

 

那么菱形继承 需要用 虚继承 来解决数据冗余的问题,格式如下图所示:

 

 

 

 

代码示例

要求:虚继承  比较 使用虚继承和 不使用虚继承 之间的区别
1 定义Farmer类
    数据成员: m_strName
    成员函数:构造函数  析构函数 sow()

2 定义Worker类:
    数据成员: m_strCode
    成员函数:构造函数  析构函数  carry()

3 定义MigrantWorker类
    数据成员:无
    成员函数: 构造函数 析构函数

4 Person 
    数据成员: m_strColor
    成员函数:构造函数  析构函数 printColor()

 

//Person.h
#pragma once
#include<iostream>
#include<string>
using namespace std;

class Person
{
public:
	Person(string clolr = "blue");//构造函数
	virtual ~Person();// virtual 防止内存泄漏

	void printColor();

protected:
	string m_strColor;

};
//Person.cpp

#include<iostream>
#include"Person.h"
using namespace std;


Person::Person(string color)
{
	m_strColor = color;
	cout << "Person()--构造" << endl;
}

Person::~Person()
{
	cout << "~Person()--析构" << endl;
}

void Person::printColor()
{
	cout << "Color: " << m_strColor << endl;
	cout << "Person--printColor()" << endl;
}

 

//Farmer.h

#pragma once
#include<iostream>
#include <string>
#include"Person.h"
using namespace std;
class Farmer :public Person
{
public:
	Farmer(string name = "Farmer_001", string color = "blue");
	virtual ~Farmer();

	void sow();

protected:
	string m_strName;
};

//Farmer.cpp
#include"Farmer.h"
using namespace std;

Farmer::Farmer(string name,string color) :Person("Farmer "+ color)

{
	m_strName = name;
	cout << "Farmer()--构造" << endl;
}

Farmer::~Farmer()
{
	cout << "~Farmer()--析构" << endl;
}

void Farmer::sow()
{
	cout << "Name= " << m_strName << endl;
	cout << "Farmer()--sow()" << endl;
}

 

 

//Worker.h

#pragma once
#include<iostream>
#include <string>
#include"Person.h"
using namespace std;
class Worker:public Person
{
public:
	Worker(string code = "Worker_001",string color="blue");
	virtual ~Worker();

	void carry();

protected:
	string m_strCode;
};
//Worker.cpp

#include<iostream>
#include"Worker.h"
using namespace std;

Worker::Worker(string code,string color):Person("Worker "+ color)
{
	m_strCode = code;
	cout << "Worker()--构造" << endl;
}

Worker::~Worker()
{
	cout << "~Worker()--析构" << endl;
}

void Worker::carry()
{
	cout << "Code= " << m_strCode << endl;
	cout << "Worker--carry()" << endl;
}

 

//MigrantWorker.h
#pragma once
#include<iostream>
#include <string>
#include"Worker.h"
#include"Farmer.h"
using namespace std;


class MigrantWorker :public Worker, public Farmer //继承两个类
{
public:
	MigrantWorker(string name, string code,string color);
	~MigrantWorker();
};
//MigrantWorker.cpp

#include"MigrantWorker.h"
using namespace std;
MigrantWorker::MigrantWorker(string name, string code,string color) :Farmer(name,color), Worker(code,color)
{
	cout << "MigrantWorker()--构造" << endl;
}


MigrantWorker::~MigrantWorker()
{
	cout << "~MigrantWorker()--析构" << endl;
}

 

//main.cpp

#include<iostream>
#include"MigrantWorker.h"
using namespace std;
/*************************

要求:虚继承  比较 使用虚继承和 不使用虚继承 之间的区别
1 定义Farmer类
	数据成员: m_strName
	成员函数:构造函数  析构函数 sow()

2 定义Worker类:
	数据成员: m_strCode
	成员函数:构造函数  析构函数  carry()

3 定义MigrantWorker类
	数据成员:无
	成员函数: 构造函数 析构函数

4 Person 
	数据成员: m_strColor
	成员函数:构造函数  析构函数 printColor()
**************************/

int main()
{
	MigrantWorker *p = new MigrantWorker("HAHA", "002","black");
	cout << "---------- 1 -----------" << endl;
	cout << "" << endl;

	p->Farmer::printColor();
	cout << "---------- 2 -----------" << endl;
	p->Worker::printColor();

	cout << "---------- 3 -----------" << endl;
	cout << "" << endl;

	delete p;
	p = NULL;


	cin.get();
	return 0;
}

 

上面没有使用虚继承的运行结果:

 

 

 

接下来 分别 在Farmer.hWorker.h 中加入 virtual 关键字(使用虚继承)

//Farmer.h  加入虚继承

#pragma once
#include<iostream>
#include <string>
#include"Person.h"
using namespace std;
class Farmer :virtual public Person//虚继承
{
public:
	Farmer(string name = "Farmer_001", string color = "blue");
	virtual ~Farmer();

	void sow();

protected:
	string m_strName;
};

//Worker.h 加入虚继承

#pragma once
#include<iostream>
#include <string>
#include"Person.h"
using namespace std;
class Worker:virtual public Person//虚继承
{
public:
	Worker(string code = "Worker_001",string color="blue");
	virtual ~Worker();

	void carry();

protected:
	string m_strCode;
};

 

运行结果:

 

 


参考资料

[1] C++远征之继承篇  (注:图片均来自视频中PPT)

 

  • 27
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C++工资管理系统多继承、虚函数、虚基类的实现方法如下: 1. 多继承 多继承是指一个类可以从多个基类中继承属性和方法。在C++中,可以通过在类定义中使用逗号分隔多个基类来实现多继承。例如: ```cpp class Base1 { public: void func1(); }; class Base2 { public: void func2(); }; class Derived : public Base1, public Base2 { public: void func3(); }; ``` 在上面的例子中,Derived类从Base1和Base2两个基类中继承了属性和方法。 2. 虚函数 虚函数是指在基类中声明的函数,在派生类中可以被重。在C++中,可以通过在函数声明前加上virtual关键字来声明虚函数。例如: ```cpp class Base { public: virtual void func(); }; class Derived : public Base { public: void func(); // 重了Base类中的虚函数 }; ``` 在上面的例子中,Base类中的func()函数是虚函数,Derived类中的func()函数重了Base类中的虚函数。 3. 虚基类 虚基类是指在多重继承中,为了避免派生类中出现多个基类的副本,而将某个基类设置为虚基类。在C++中,可以通过在基类名前加上virtual关键字来声明虚基类。例如: ```cpp class Base { public: int num; }; class Base1 : virtual public Base { public: void func1(); }; class Base2 : virtual public Base { public: void func2(); }; class Derived : public Base1, public Base2 { public: void func3(); }; ``` 在上面的例子中,Base类被声明为虚基类,Derived类中只包含一个Base类的副本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TechArtisan6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值