我知道当你想声明一个多态函数时,你必须将基类函数声明为虚拟。
class Base
{
public:
virtual void f();
};
我的问题是你是否需要将继承类函数声明为虚拟,即使预期Child的行为就像是“密封”一样?
class Child : public Base
{
public:
void f();
};
答案 0 :(得分:7)
不,您不需要重新声明虚拟功能。
基类中的virtual
函数会自动将所有重写函数声明为虚函数:
struct A
{
void foo(); //not virtual
};
struct B : A
{
virtual void foo(); //virtual
}
struct C : B
{
void foo(); //virtual
}
答案 1 :(得分:0)
在Child中将f()声明为虚拟有助于某人阅读Child的定义。它作为文档非常有用。
答案 2 :(得分:0)
一旦基类覆盖被标记为virtual
,所有其他覆盖都是隐含的。虽然您不需要将该功能标记为virtual
,但我倾向于将其用于文档目的。
从最后一部分开始:即使预计Child会表现得像是“密封”了吗?,如果你想密封这个类,你实际上可以通过创建一个 seal 类来完成C ++ 11(这在C ++ 03中无法完全实现):
template <typename T>
class seal {
seal() {}
friend T;
};
然后继承你的密封类(CRTP):
class Child : public Base, virtual seal<Child> {
// ...
};
诀窍在于,由于使用了虚拟继承,层次结构中派生类型最多的类型必须调用虚拟基础构造函数(在本例中为seal<Child>
),但该构造函数在模板化类中是私有的,并且仅通过Child
声明提供给friend
。
在C ++中,你必须为你想要密封的每个类创建一个seal
类型,或者使用一个没有提供完美密封的通用方法(它可以被篡改)