我是靠谱客的博主 天真帆布鞋,最近开发中收集的这篇文章主要介绍virtual与override的区别,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

两者都是用于派生类重写基类的方法,其中virtual主要是在运行阶段实现多态,override主要是用在编译阶段语法检查。

一、virtual实现多态(重写)

1. 在使用基类指针时,调用的方法如果是virtual函数,子类只要重写,不管是否声明为virtual,都可以实现多态。

class QTestBase {
public:
	void testFunc() {
		qDebug() << "Test --- QTestBase::testFunc";
	}
};
class QTestChild : public QTestBase {
public:
	void testFunc() {
		qDebug() << "Test --- QTestChild::testFunc";
	}
};
class QTestChildEx : public QTestChild {
public:
	void testFunc() {
		qDebug() << "Test --- QTestChildEx::testFunc";
	}
};

定义test方法,验证上述结果:

void Test()
{
	QTestBase *pTest = new QTestChildEx();
	pTest->testFunc();
}

// Debug输出:Test --- QTestBase::testFunc

指针为QTestBase*类型,实际实例化的是QTestChildEx对象。testFunc()在QTestBase类中被定义为普通成员函数,即使子类重写了该方法,通过指针调用的仍然是QTestBase的方法。

2. 将QTestBase类中的testFunc()方法定义为虚函数。

class QTestBase {
public:
	virtual void testFunc() {
		qDebug() << "Test --- QTestBase::testFunc";
	}
};

即使QTestChild类和QTestChildEx类在重写testFunc()方法时,都未声明成virtual,但在实际应用中,基类指针调用testFunc()时,仍视为虚函数,实现多态效果。

Debug的输出结果:Test --- QTestChildEx::testFunc。

3. 如果指针被定义为QTestChild*,虽然QTestChild类中重写了testFunc()方法,且声明时并未加上virtual,但是仍能实现多态。

void Test()
{
	QTestChild *pTest = new QTestChildEx();
	pTest->testFunc();
}

// Debug结果:Test --- QTestChildEx::testFunc

总结:只要基类中的方法被声明为虚拟函数(virtual)了,基于其派生的子类,在重写此方法时,不管是否声明为virtual,都可以实现多态。

如果基类该方法未声明为虚函数,而是中间的子类重写函数声明了virtual,以中间子类为始,其后的派生类,该方法都视为虚函数。

4. 将基类QTestBase中的testFunction()方法定义为普通函数,而在QTestChild类中将该方法声明为虚函数。

class QTestBase {
public:
	void testFunc() {
		qDebug() << "Test --- QTestBase::testFunc";
	}
};
class QTestChild : public QTestBase {
public:
	virtual void testFunc() {
		qDebug() << "Test --- QTestChild::testFunc";
	}
};
class QTestChildEx : public QTestChild {
public:
	void testFunc() {
		qDebug() << "Test --- QTestChildEx::testFunc";
	}
};
class QTestChildEx2 : public QTestChildEx {
public:
	void testFunc() {
		qDebug() << "Test --- QTestChildEx2::testFunc";
	}
};

通过三种基类指针,测试结果如下: 

void Test()
{
	QTestBase *pTest = new QTestChildEx2();
	pTest->testFunc();
}
// Debug输出结果:Test --- QTestBase::testFunc

void Test()
{
	QTestChild *pTest = new QTestChildEx2();
	pTest->testFunc();
}
// Debug输出结果:Test --- QTestChildEx2::testFunc

void Test()
{
	QTestChildEx *pTest = new QTestChildEx2();
	pTest->testFunc();
}
// Debug输出结果:Test --- QTestChildEx2::testFunc

二、override(重写)

若使用override显式的说明重写某个函数,必须满足以下几个条件:

1、基类中必须已经声明了该方法,且必须声明为virtual方法,函数名、形参类型、常量属性 (constness) 和 引用限定符;

2、基类和派生类中,成员函数的返回类型和异常规格必须兼容。

编译错误情况一(基类未声明,子类定义override方法),如下所示:

class QTestBase {
public:
	void testFunc() {
		qDebug() << "Test --- QTestBase::testFunc";
	}
};
class QTestChild : public QTestBase {
public:
	virtual  void testFunc() {
		qDebug() << "Test --- QTestChild::testFunc";
	}
	void testFunc2() override {
		qDebug() << "Test --- QTestChild::testFunc2";
	}
};

// 编译时报错:error C3668: “QTestChild::testFunc2”: 包含重写说明符“override”的方法没有重写任何基类方法 (编译源文件 QTestChild.cpp)

编译错误情况二(基类已声明,但不是virtual方法,子类定义override方法),如下所示:

class QTestBase {
public:
	void testFunc() {
		qDebug() << "Test --- QTestBase::testFunc";
	}
	void testFunc2() {
		qDebug() << "Test --- QTestBase::testFunc2";
	}
};
class QTestChild : public QTestBase {
public:
	virtual  void testFunc() {
		qDebug() << "Test --- QTestChild::testFunc";
	}
	void testFunc2() override {
		qDebug() << "Test --- QTestChild::testFunc2";
	}
};

// 编译时报错:error C3668: “QTestChild::testFunc2”: 包含重写说明符“override”的方法没有重写任何基类方法 (编译源文件 QTestChildEx.cpp)

对于子类重写父类的方法上添加override,不影响类的多态特性。 override只是在编译阶段进行语法检查,提前找出错误。

在子类中virtual和override可以同时存在,即使不加virtual也不影响多态。

class QTestBase {
public:
	void testFunc() {
		qDebug() << "Test --- QTestBase::testFunc";
	}
	void testFunc2() { // 未声明virtual,若通过QTestBase *指针,调用testFunc2不能实现多态
		qDebug() << "Test --- QTestBase::testFunc2";
	}
};
class QTestChild : public QTestBase {
public:
	virtual  void testFunc() {
		qDebug() << "Test --- QTestChild::testFunc";
	}
	virtual void testFunc2() { // 已声明virtual
		qDebug() << "Test --- QTestChild::testFunc2";
	}
};
class QTestChildEx : public QTestChild {
public:
	void testFunc() {
		qDebug() << "Test --- QTestChildEx::testFunc";
	}
    // 未重写此方法
};
class QTestChildEx2 : public QTestChildEx {
public:
	void testFunc() {
		qDebug() << "Test --- QTestChildEx2::testFunc";
	}
	virtual void testFunc2() override { // virtual 和 override 关键字同时存在
		qDebug() << "Test --- QTestChildEx2::testFunc2";
	}
};

最后

以上就是天真帆布鞋为你收集整理的virtual与override的区别的全部内容,希望文章能够帮你解决virtual与override的区别所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部