继承(二)

转换与继承

派生类对象也是基类对象。这意味着在使用基类的地方可以用派生类来替换。

派生类到基类的转换

1.当派生类以public方式继承基类时,编译器可自动执行的转换(向上转换upcasting安全转换)
	1.1 派生类对象指针自动转化为基类对象指针
	1.2 派生类对象引用自动转化为基类对象引用
	1.3 派生类对象自动转化为基类对象(特有的成员消失)
	
2.当派生类以private/protected方式继承基类时
	2.1 派生类对象指针(引用)转化为基类对象指针(引用)需用强制类型转化。但不能用static_cast,要用reinterpret_cast
		### 回顾C++转型(static_cast、reinterpret_cast、const_cast、dynamic_cast)
	2.2 不能把派生类对象强制转化为基类对象

基类到派生类的转换

1.基类对象指针(引用)可用强制类型转化为派生类对象指针(引用),而基类对象无法执行这类转换。

2.向下转型不安全,没有自动转换的机制。
#include <iostream>

using namespace std;

class Employee
{
public:
	Employee(const string& name, const int age, const int deptno) : name_(name), age_(age), deptno_(deptno)
	{
		cout << "Employee ..." << endl;
	}

	~Employee()
	{
		cout << "~Employee ..." << endl;
	}
private:
	string name_;
	int age_;
	int deptno_;
};

class Manager : public Employee
{
public:
	Manager(const string& name, const int age, const int deptno, int level) : Employee(name, age, deptno), level_(level)
	{
		cout << "Manager ..." << endl;
	}

	~Manager()
	{
		cout << "~Manager ..." << endl;
	}
private:
	int level_;
};

class Manager2 : private Employee
{
public:
	Manager2(const string& name, const int age, const int deptno, int level) : Employee(name, age, deptno), level_(level)
	{
		cout << "Manager2 ..." << endl;
	}

	~Manager2()
	{
		cout << "~Manager2 ..." << endl;
	}
private:
	int level_;
};

int main()
{
	Employee e1("jack", 25, 20);
	Manager m1("ma", 30, 20, 10);
	Manager2 m2("yun", 50, 40, 20);
	Employee* pe;
	Manager* pm;
	Manager2* pm2;

	cout << "派生类到基类的转换" << endl;
	cout << "public..." << endl;
	cout << endl;

	pe = &e1;
	pm = &m1;

	pe = &m1;	//	(public继承)派生类指针(引用)可以转化为基类指针(引用)。将派生类对象看成基类对象
	//pm = &e1;	//	Error,基类指针无法转化为派生类指针。无法将基类对象看成派生类对象
	
	e1 = m1;	//	派生类对象可以转化为基类对象,会产生对象切割object slicing(特有的成员消失)


	cout << "private/protected..." << endl;
	cout << endl;

	pm2 = &m2;
	//pe = pm2;	//	Error,(private/protected继承)派生类对象指针(引用)不能自动转化为基类对象指针(引用),
	
	//pe = static_cast<Employee*> (pm2);	//	Error
	
	pe = reinterpret_cast<Employee*>(pm2);	//	C++,需用强制类型转化。
	//pe = (Employee*)&m2;	//	C风格,OK
	
	//e1 = m2;	//	Error,派生类对象无法强制转化为基类对象


	cout << "***************" << endl;
	cout << "基类到派生类的转换" << endl;
	cout << endl;

	pm = static_cast<Manager*>(pe);
	pm2 = static_cast<Manager2*>(pe);	//	基类对象指针(引用)可用强制类型转化为派生类对象指针(引用),
										//	但是不安全,eg:pm->level_访问不到。
	//m1 = e1;							//	Error,基类对象无法执行这类转换。
	
	
	return 0;
}

在这里插入图片描述

多重继承

1.单重继承:一个派生类最多只能有一个基类

2.多重继承:一个派生类可以有多个基类
	class 类名:继承方式 基类1, 继承方式 基类2,...
	{...};
	派生类同时继承多个基类的成员,更好的软件重用
	可能会有大量的二义性,多个基类中可能包含同名变量或函数
3.多重继承中解决访问歧义的方法
	基类名::数据成员名(或成员函数(参数表))
	明确指明要访问定义于哪个基类中的成员

虚继承与虚基类

1.当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生二义性------采用虚基类来解决。

2.虚基类的引入
	用于有共同基类的场合
	
3.声明
	以virtual修饰说明基类
	eg:class B1:virtual public BB
	
4.作用
	4.1主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题。
	4.2为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝。

虚基类及其派生类构造函数

1.虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。

2.在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始列表中给出对虚基类的构造函数的调用。如果未列出,则表示调用该基类的默认构造函数。

3.在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数,该派生类的其他基类对虚基类构造函数的调用被忽略。
#include <iostream>

using namespace std;

class Furniture
{
public:
	Furniture(const int weight) : weight_(weight)
	{
		cout << "Furniture ..." << endl;
	}

	~Furniture()
	{
		cout << "~Furniture ..." << endl;
	}
	int weight_;
};

class Bed : virtual public Furniture
{
public:
	Bed(const int weight) : Furniture(weight)
	{
		cout << "Bed ..." << endl;
	}

	void Sleep()
	{
		cout << "Sleep ..." << endl;
	}

	~Bed()
	{
		cout << "~Bed ..." << endl;
	}
};

class Sofa : virtual public Furniture
{
public:
	Sofa(const int weight) : Furniture(weight)
	{
		cout << "Sofa ..." << endl;
	}

	void WatchTV()
	{
		cout << "WatchTV ..." << endl;
	}

	~Sofa()
	{
		cout << "~Sofa ..." << endl;
	}
};

class SofaBed : public Bed, public Sofa
{
public:
	SofaBed(int weight) : Bed(weight), Sofa(weight),  Furniture(weight)
	{
		cout << "SofaBed ..." << endl;
	}

	void FoldIn()
	{
		cout << "FoldIn ..." << endl;
	}

	void FoldOut()
	{
		cout << "FoldOut ..." << endl;
	}


	~SofaBed()
	{
		cout << "~SofaBed ..." << endl;
	}
};

int main()
{
	SofaBed softbed(10);
	
	softbed.weight_ = 20;
	return 0;
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值