C++笔记-对“继承”的进一步认识(2024-08-15)

此篇博文在笔记库的时间是2024-08-15,公布到互联网的时间是2024-11-18。

基础知识点

在C++中,如果发现有了继承关系,那么注定会有,父类指针指向子类对象。父类指针调用子类方法。这里重点说下虚函数和非虚函数:

虚函数

非虚函数

定义和声明

使用 virtual 关键字声明,在基类中定义,允许在派生类中重写。

没有 virtual 关键字,不能被重写,派生类中同名的函数只是隐藏了基类的同名函数。

调用机制

使用动态绑定(或晚绑定)。函数调用在运行时根据对象的实际类型确定。

使用静态绑定(或早绑定)。函数调用在编译时根据指针或引用的类型确定。

适用场景

用于需要多态性时,例如想要实现不同类之间的统一接口时。

用于仅在基类中需要固定行为,且不需要在派生类中改变的情况。

性能

由于需要使用虚表(vtable)和指针,有一定的性能开销。

由于直接调用,没有额外的开销,通常效率更高。

析构函数

类的设计中,如果基类有虚函数,通常将析构函数声明为虚的,以确保派生类的析构函数能够被正确调用。

如果一个类的析构函数是非虚的,而通过基类指针删除派生类对象,可能导致资源泄漏和未定义行为。

补充知识点

上面是基础知识,下面来一些值得思考的知识点(编译器用的是MSVC2015):

如下类定义代码:

class Base {
public:
	void print() { cout << "Base print" << endl; }
};

class A : public Base {
public:
	void print() { cout << "A print" << endl; }
};

如下调用:

	Base *base = new Base;
	base->print();
	((A*)base)->print();
        delete base;

运行结果如下:

这里就有点看开始奇怪了,这里的base变量是用父类new的,第二个打印只是强转成了A*,然后成功打印了A类的print,我感觉应该会运行时报错或者打印Base的print也能理解。因为A的print并没有被构造。再看下下面

如果把类定义改成:

class Base {
public:
	virtual void print() { cout << "Base print" << endl; }
};

class A : public Base {
public:
	void print() { cout << "A print" << endl; }
};

运行截图如下:

	Base *base = new Base;
	base->print();
	((A*)base)->print();
        delete base;

加了virtual就好理解了,新加了个虚表的概念,调用print,就直接从虚表中拿函数地址,因为没有new A,所以虚表没有被刷掉,调用的还是Base类的print。

而上面那个例子,可以看出,在计算机底层中,还有个内存块,专门存储了成员函数。估计在定义时就有了。

当然不推荐大家这么使用。因为例子中给的函数很简单,如果比较复杂,比如这样的:

定义如下:

class Base {
public:
	void print() { cout << "Base print" << endl; }
};

class A : public Base {
public:
	A() { value1 = 1; }
	void print() { cout << "A print : " << value1 << endl; }

private:
	int value1;
};

调用如下:

	Base *base = new Base;
	base->print();
	((A*)base)->print();
        delete base;

运行截图如下:

就开始有问题了,打印的就不知道是哪块内存的数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IT1995

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

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

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

打赏作者

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

抵扣说明:

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

余额充值