继承(三)

本文探讨了C++中不同类型转换的细节,包括派生类到基类的自动转换和基类到派生类的手动转换。文章通过具体代码示例展示了不同继承方式下类型转换的特点,并解释了向上转型和向下转型的区别。

1.转化与继承

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

2.派生类到基类的转换

  (1) 当派生类以public方式继承基类时,编译器可自动执行的转换(向上转行upcasting安全转换)

             [1]派生类对象指针自动转化为基类对象指针

             [2]派生类对象引用自动转化为基类对象引用

             [3]派生类对象自动转化为基类对象(特有的成员消失)

  (2)当派生类以private/protected方式继承基类时

             [1]派生类对象指针(引用)转化为基类对象指针(引用)需用强制类型转化。但不能用static_cast,要用reinterpret_cast

             [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) {
	}
public:
	string name_;
	int age_;
	int deptno_;
};

class Manager : public Employee {
public:
	Manager(const string& name, const int age, const int deptno, int leve1) : Employee(name, age, deptno), leve1_(leve1) {
	}
private:
	int leve1_;
};

class Manager2 : private Employee {
public:
	Manager2(const string& name, const int age, const int deptno, int leve1) : Employee(name, age, deptno), leve1_(leve1) {
	}
private:
	int leve1_;
};

int main(void) {
	
	Employee e1("zhangsan", 25, 20);
	Manager m1("lisi", 38, 20 ,10);
	Manager2 m2("wangwu", 40, 15 ,8);
	Employee* pe;
	Manager* pm;
	Manager2* pm2;
	
	pe = &e1;
	pm = & m1;
	pm2 = & m2;


	//1.-------------派生类字刚氇转化为基类指针-------
	pe = &m1;  //派生类指针可以转化为基类指针。将派生类对象看成基类对象
	pe = pm;
	//pm = &e1;  //基类指针无法转化为派生类指针。无法将基类对象看成是派生类对象

	//2.----------------派生类对象转化为基类对象------------------
	e1 = m1; //派生类对象可以转化为基类对象。将派生类对象看成基类对象
		 //会产生对象切割(派生类特有成员消失)。object slicing
	
	//3.---------------private,protected派生类指针转化为  基类指针----------------
	//pe = pm2;  //私有或保护继承的时候,派生类对象指针不可以自动转化为基类对象指针
	//pe = static_cast<Employee*>(pm2);
	pe = reinterpret_cast<Employee*>(pm2);
	pe = (Employee*)pm2;
	
	//4.--------------private,protected派生类对象转化为基类对象-----------------
	//e1 = m2; // 私有或保护继承的时候,派生类对象无法转化基类对象
	//e1 = reinterpret<Employee>(m2);   // 私有或保护继承的时候,派生类对象无强? 转化 为基类对象

	//5.-----------基类指针  转化为 派生类指针--------------------
	pm = static_cast<Manager*>(pe);  //基类指针可以强制转化为派生类指针,但是不安全
	pm2 = reinterpret_cast<Manager2*>(pe); 

	//6.-----------基类对象 转化为 派生类对象 ----------------
	//m1 = reinterpret_cast<Manager>e1;  //基类对象无法转为派生类对象 
	return 0;
}


3.基类到派生类的转换

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

   (2)向下转型不安全,没有自动转换的机制

#include <iostream>
using namespace std;

class Manager;

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

class Manager : public Employee {
public:
	Manager(const string& name, const int age, const int deptno, int leve1) : Employee(name, age, deptno), leve1_(leve1) {
	}
	//从语法上来演示基类对象可以转化为派生类对象,但是没有意义
	/*Manager(const Employee& other): Employee(other), leve1_(-1) {
	cout << "Manager(const Employee& other)" << endl;	
	}*/
private:
	int leve1_;
};

//语法上来演示基类对象可以转化为派生类对象,但是没有意义
Employee::operator Manager() {
	return Manager(name_, age_, deptno_, -1);	
}
int main(void) {
	
	Employee e1("zhangsan", 25, 20);
	Manager m1("lisi", 38, 20 ,10);
	
	m1 = e1;

	
	return 0;
}

转换构造函数,将其它类型转换为类类型

类型转换运算符重载,将类类型转换为其它类型

### C++ 多继承中公共继承、保护继承和私有继承的作用 在 C++ 的多继承机制中,派生类可以通过种不同的继承方式(公共继承、保护继承和私有继承)从基类继承成员。这继承方式决定了派生类及其子类对基类成员的访问权限。 #### 1. 公共继承(Public Inheritance) 公共继承是最常见的继承方式,表示“is-a”关系。在这种继承方式下,基类的公有成员在派生类中仍然是公有的,而受保护成员则保持受保护状态。例如: ```cpp class Base { public: void publicFunc() {} protected: void protectedFunc() {} }; class Derived : public Base {}; // 公共继承 ``` 在此示例中,`Derived` 类中的 `publicFunc` 方法仍然可以被外部访问,而 `protectedFunc` 则只能被 `Derived` 及其派生类访问[^1]。 #### 2. 保护继承(Protected Inheritance) 保护继承表示“has-a”或“part-of”关系,主要用于限制外部对基类成员的访问。在这种继承方式下,基类的公有成员和受保护成员在派生类中都变为受保护成员,无法被外部直接访问。例如: ```cpp class Derived : protected Base {}; // 保护继承 ``` 此时,即使 `Base::publicFunc` 在基类中是公有的,在 `Derived` 中也变成了受保护成员,只有 `Derived` 及其派生类可以访问[^2]。 #### 3. 私有继承(Private Inheritance) 私有继承表示“implemented-in-terms-of”关系,类似于组合模式。在这种继承方式下,基类的所有成员在派生类中都变为私有成员,无法被外部或派生类的子类访问。例如: ```cpp class Derived : private Base {}; // 私有继承 ``` 在此情况下,即使 `Base::publicFunc` 是公有的,它在 `Derived` 中也变为私有成员,仅限于 `Derived` 内部使用[^3]。 --- ### 菱形继承问题及解决方法 菱形继承是多继承中的一种特殊情况,当两个或多个中间基类共同继承自同一个间接基类时,派生类中可能会出现该间接基类的多份副本,从而导致二义性和冗余问题[^4]。 #### 解决方法:虚拟继承(Virtual Inheritance) 为了解决菱形继承问题,C++ 提供了虚拟继承机制。通过在继承声明中使用 `virtual` 关键字,可以确保间接基类在派生类中只存在一份实例,从而消除冗余和二义性。例如: ```cpp class A { public: int val; }; class B : virtual public A {}; // 虚拟继承 A class C : virtual public A {}; // 虚拟继承 A class D : public B, public C {}; // D 同时继承 B 和 C ``` 在此示例中,`D` 类中只有一份 `A` 类的实例,无论通过 `B` 还是 `C` 访问 `A` 的成员,最终指向的都是同一份实例,从而解决了二义性和冗余问题[^5]。 --- ### 注意事项 尽管虚拟继承能够有效解决菱形继承问题,但其也会带来一定的复杂性和性能开销。具体来说: - 虚拟继承增加了对象的内存占用,因为需要额外存储虚拟基类指针。 - 访问虚拟基类的成员时可能需要额外的间接寻址操作,从而影响运行效率。 因此,在设计多继承结构时,应权衡灵活性与性能之间的关系,合理选择是否使用虚拟继承。 --- ### 示例代码 以下是一个完整的示例,展示了如何通过虚拟继承解决菱形继承问题: ```cpp #include <iostream> class A { public: int val; A(int v = 0) : val(v) {} void print() { std::cout << "A: " << val << std::endl; } }; class B : virtual public A {}; // 虚拟继承 A class C : virtual public A {}; // 虚拟继承 A class D : public B, public C {}; // D 同时继承 B 和 C int main() { D d; d.A::val = 10; // 正确:通过指定作用域解决歧义 d.print(); // 输出:A: 10 return 0; } ``` --- ### 总结 - 公共继承、保护继承和私有继承分别适用于不同的场景,开发者应根据实际需求选择合适的继承方式。 - 菱形继承问题是多继承中常见的挑战,通过虚拟继承可以有效解决二义性和冗余问题。 - 使用虚拟继承时需注意其带来的性能开销和复杂性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值