虚基类和虚继承

抽象类(有纯虚函数的类) / 虚基类
virtual:
1.修饰成员方法是虚函数
2.可以修饰继承方式,是虚继承。被虚继承的类,称作虚基类。

vfptr/vbptr
vftable/vbtable

在这里插入图片描述

在Windows vs下会存在内存释放错误的问题,Linux g++下自动修正。

在这里插入图片描述
命令:cl 继承与多态.cpp /d1reportSingleClassLayout 可以查看内存布局。

在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;

class A {
public:
	virtual void func() { cout << "call A::func" << endl; }
	void operator delete(void *ptr) {
		cout << "operator delete p:" << ptr << endl; 
		free(ptr);
	}
		
private:
	int ma;
};

class B : virtual public A {
public:
	void func() { cout << "call B::func" << endl; }
	void *operator new(size_t size) {
		void *p = malloc(size); 
		cout << "operator new p:" << p << endl;
		return p;
	}
		
private:
	int mb;
};

/*
A a; 4个字节
B b; ma,mb   8个字节+4 = 12个字节  vbptr
*/
int main() {
	////基类指针指向派生类对象,永远指向的是派生类基类部分数据的起始地址
	//A *p = new B(); // B::vftable
	//p->func();
	//delete p;

	B b;
	A *p = &b;
	p->func();

	return 0;
}

### C++虚基类虚继承的概念及用法 #### 虚基类的概念与作用 在C++中,虚基类是一种特殊的继承方式,用于解决多重继承带来的二义性重复数据成员的问题。当一个派生类从多个基类派生而来,而这些基类又共同继承同一个祖先类时,可能会导致该祖先类被多次实例化的情况。这种现象被称为“菱形继承问题”。为了避免这种情况的发生,C++提供了虚继承机制[^1]。 通过使用`virtual`关键字修饰继承关系,可以让所有间接派生的子类共享同一份基类实例,从而消除冗余的数据成员并简化程序逻辑[^3]。 #### 虚继承的应用场景 虚继承主要应用于复杂的类层次结构中,特别是涉及多重继承的情况下。例如,在设计图形界面库或者游戏引擎等大型软件项目时,经常会出现这样的需求——某些功能模块可能需要同时具备多种行为特征(即它们是从不同父类派生出来的),但又要确保不会因为过度复制而导致资源浪费或操作混乱[^2]。 下面是一个典型的例子: ```cpp class Base { public: int baseValue; }; // 定义两个中间层类,并都采用虚拟方式继承自Base class DerivedA : virtual public Base {}; class DerivedB : virtual public Base {}; // 终极派生类同时继承于DerivedADerivedB class FinalClass : public DerivedA, public DerivedB {}; int main(){ FinalClass obj; // 不管FinalClass如何组合其直接父母节点, // 都只会保留唯一的一份来自Base的基础属性。 obj.baseValue = 42; cout << "The value is: " << obj.baseValue << endl; return 0; } ``` 在这个示例里,无论 `FinalClass` 是怎样由 `DerivedA` `DerivedB` 构建起来的,它最终都会维持单一版本的 `baseValue` 成员变量。 #### 实现细节分析 需要注意的是,虽然表面上看似乎只是简单加了个关键词而已,但实际上编译器背后做了很多额外工作来支持这一特性。比如调整构造顺序、增加指向虚表(vtable) 的指针等等。因此相较于普通的单向线性继承而言,性能开销会稍大一点;不过考虑到现代计算机硬件的能力以及由此获得的好处,这点代价通常是值得接受的[^4]。 另外值得注意的一个地方在于初始化列表上:对于虚基类来说,即使某个特定路径上的某级子类别已经对其进行了设定,最末端的实际创建实体仍然负有责任去显式指定参数给定值。这是因为只有后者才知道确切的需求是什么样的。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值