考虑具有函数class Base
的基类virtual void foo(void)
。该功能在Base
中实现;即不是纯粹的虚拟。
我是否可以使用哪种模式在继承此类时,即class Child : public Base
,迫使我覆盖foo
?
答案 0 :(得分:3)
除了使其成为纯虚函数外,无法进行覆盖。
请注意,函数被标记为纯虚拟的事实并不意味着它不能在基类中具有实现 - 这仅意味着派生类必须覆盖它。
struct Base {
virtual void foo() = 0; // foo() is pure virtual
};
struct Derived : public Base {
void foo() { // Derived overrides the pure virtual
cout << "Hello ";
Base::foo(); // Call the implementation in the base
cout << endl;
}
};
void Base::foo() {
cout << " world";
}
int main() {
Derived d;
d.foo();
return 0;
}
这将打印"Hello world"
,"world"
部分来自基类中的实现。
答案 1 :(得分:3)
C ++ 11引入了the override
keyword来帮助解决这个问题:
struct Base
{
void foo();
};
struct Derived : Base
{
void foo() override; // error! Base::foo is not virtual
};
但是你不能在Base
本身写这个以获得相同的效果;即没有mustoverride
说明符。最终,Base
关于派生类执行或不覆盖的业务都不是。
你可以保持Base
摘要,同时为纯虚函数提供“默认”定义:
struct Base
{
virtual void foo() = 0;
};
void Base::foo() {}
struct Derived : Base {}; // error! does not override Base::foo
struct Derived2: Base
{
virtual void foo() override
{
Base::foo(); // invokes "default" definition
}
};
如果您要使整个基本类型无法呈现,那么这将是一个可接受的解决方案。
答案 2 :(得分:1)
是的,实际上有:
#include <iostream>
class Base
{
public:
virtual void someFun() {std::cout << "Base::fun" << std::endl;}
virtual ~Base() {}
};
class AlmostBase : public Base
{
public:
virtual void someFun() = 0;
};
class Derived : public AlmostBase
{
public:
virtual void someFun() {std::cout << "Derived::fun" << std::endl;}
};
int main()
{
Derived *d = new Derived();
d->someFun();
delete d;
}
如果您从someFun
取消注释Derived
,编译器会抱怨...
您引入了一个具有纯虚函数的中间类AlmostBase
。这样你也可以拥有Base
个对象,现在唯一的缺点就是所有的类都需要从中间库继承。
答案 3 :(得分:1)
纯虚拟成员函数仍然可以拥有正文。唯一需要注意的是它必须在类定义之外定义。这是完全合法的C ++:
#include <iostream>
struct Base
{
virtual void foo() const = 0;
};
void Base::foo() const
{
std::cout << "Base!\n";
}
struct Derived : Base
{
// Uncomment following line to remove error:
//virtual void foo() const override { std::cout << "Derived\n"; Base::foo(); }
};
int main()
{
Derived d;
d.foo();
}
请注意,这使Base
在所有方面成为抽象类,即无法直接实例化Base
。
答案 4 :(得分:0)
你可以让base方法在调用时抛出异常,然后类必须覆盖它以避免父执行。 这在MFC FrameWork中使用,例如
// Derived class is responsible for implementing these handlers
// for owner/self draw controls (except for the optional DeleteItem)
void CComboBox::DrawItem(LPDRAWITEMSTRUCT)
{ ASSERT(FALSE); }
void CComboBox::MeasureItem(LPMEASUREITEMSTRUCT)
{ ASSERT(FALSE); }
int CComboBox::CompareItem(LPCOMPAREITEMSTRUCT)
{ ASSERT(FALSE); return 0; }
如果控件是所有者绘制的那些方法必须继承,它负责measuer,draw,...如果你在测试函数时错过了它,你会得到一个带有有用信息的断言或异常。