概述
两者都是用于派生类重写基类的方法,其中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的区别所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复