- 在 c++11 中
override
specifier防止不覆盖预期的虚拟基函数(因为签名不匹配)。 final
specifier防止无意中覆盖派生类中的函数。
=> 是否有说明符(可能是 first
或 no_override
)防止覆盖未知的基函数?
当一个虚函数被添加到一个基类时,我想得到一个编译器错误,这个基类的签名与派生类中已经存在的虚函数具有相同的签名。
编辑 4:为了保持这个问题的简单性和相关性,这里又是
原始伪代码
- 抽象
class B : A
具有private: virtual void fooHasBeenDone() = 0;
class C : B
implementsprivate: virtual void fooHasBeenDone() override { react(); }
- 现在
class A
得到一个新的private: virtual void fooHasBeenDone();
- 但是新的
A::foo
可能与原来的B::foo
有所不同。
和一个具体的例子
- 抽象
class B : A
有virtual void showPath() = 0;
表示 PainterPath class C : B
implementsvirtual void showPath() override { mPath.setVisible(); }
- 现在
class A
得到一个新的virtual void showPath();
表示文件路径 - 现在,当 A 调用 showPath() 时,B 显示 painterPath 而不是某些文件路径。
当然这是错误的,然后我应该将 B::showPath()
重命名为 B::showPainterPath()
并实现 B::showPath () override
也是。我只想得到编译器的通知。
这是一个编译真实世界的例子:
#include <iostream>
#define A_WITH_SHOWPATH
class A
{
#ifdef A_WITH_SHOWPATH
public:
void setPath(std::string const &filepath) {
std::cout << "File path set to '" << filepath << "'. Display it:\n";
showPath();
}
// to be called from outside, supposed to display file path
virtual void showPath() {
std::cout << "Displaying not implemented.\n";
}
#else
// has no showPath() function
#endif
};
class B : public A
{
public:
virtual void showPath() = 0; // to be called from outside
};
class C1 : public B {
public:
virtual void showPath() override {
std::cout << "C1 showing painter path as graphic\n";
}
};
class C2 : public B {
public:
virtual void showPath() override {
std::cout << "C2 showing painter path as widget\n";
}
};
int main() {
B* b1 = new C1();
B* b2 = new C2();
std::cout << "Should say 'C1 showing painter path as graphic':\n";
b1->showPath();
std::cout << "---------------------------\n";
std::cout << "Should say 'C2 showing painter path as widget':\n";
b2->showPath();
std::cout << "---------------------------\n";
#ifdef A_WITH_SHOWPATH
std::cout << "Should give compiler warning\n or say \"File path set to 'Test'. Display it:\"\n and \"Displaying not implemented.\",\n but not \"C1 showing painter path as graphic\":\n";
b1->setPath("Test");
std::cout << "# Calling setPath(\"Test\") on a B pointer now also displays the\n# PainterPath, which is not the intended behavior.\n";
std::cout << "# The setPath() function in B should be marked to never override\n# any function from the base class.\n";
std::cout << "---------------------------\n";
#endif
return 0;
}
运行它并查看文本输出。
作为引用,一个具有特定用例的旧示例(PainterPath 实例):
https://ideone.com/6q0cPD (链接可能已过期)
最佳答案
first
或 no_override
等说明符的功能本身并不存在。可能是因为它可能会造成困惑。然而,它可以通过改变方法来轻松实现。
应该在基类中使用 final
说明符 添加任何新方法。这将有助于获得任何匹配签名的编译器错误。因为,它会让后续的派生类方法签名自动成为同类中的“第一”。稍后可以删除 final
关键字,因为它仅用于“第一手验证”。
在新添加的基本方法之后添加和删除 final
关键字类似于使用 debug (g++ -g
) 选项编译二进制文件,这有助于修复错误。在生产中,调试选项被删除以进行优化。
从你的例子:
class A {}; // no method, no worry
class B {
public: virtual void showPath() = 0; // ok
};
...
现在不小心在 A
中添加了类似的方法,导致错误:
class A {
public: virtual void showPath() final; // same signature by chance
// remove the `final` specifier once the signature is negotiated
};
class B {
public: virtual void showPath() = 0; // ERROR
};
因此必须协商新的 A::showPath()
和现有的 B::showPath()
之间的签名,然后通过删除 final 继续
说明符。
关于c++ - c++ `override`/`final` 说明符的反义词是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38656443/