当我用C ++编写接口类时,我选择以下两个选项之一
class Interface
{
public:
virtual R1 f1(p11, p12 , ...) = 0;
...
virtual Rn fn(pn1, pn2 , ...) = 0;
virtual ~Interface() {}
}
或
class Interface
{
public:
virtual R1 f1(p11, p12 , ...) = 0;
...
virtual Rn fn(pn1, pn2 , ...) = 0;
virtual ~Interface() = 0;
}
Interface::~Interface() {}
第一个版本更短,可以写入 第二个是有吸引力的,因为接口的所有功能都是纯虚拟的
有什么理由我更喜欢一种或另一种方法(或者可能是第三种方法)?
感谢
答案 0 :(得分:5)
据我了解,制作虚拟函数纯虚拟的目的是强制派生类为其提供实现,或者通过显式编写{选择默认实现Base::f()
中的{1}}。
如果这是真的,那么制作虚拟析构函数Derived::f()
的目的是什么?它是否强制派生类为pure virtual
提供实现?派生类可以实现Base::~Base()
吗?没有。
这意味着,带有Base::~Base()
析构函数的第一个版本似乎足以满足 所有目的。毕竟,虚拟析构函数最常见的目的是客户端可以通过类型virtual
的指针正确delete
派生类的对象。
但是,如果您仅在Base*
虚拟中创建所有功能,不 纯虚拟,并为它们提供实施(实际上你要提供),同时你想要Base
抽象类型,然后在{{1}中有一个纯虚拟析构函数}是唯一的解决方案:
Base
希望有所帮助。
答案 1 :(得分:2)
对我而言,dtor不是界面的一部分。 fi()在其他语言中会有类似物,而不是dtor。同样,您可以为fi()编写前置和后置条件,但不能写入dtor。这使得它只是一个C ++疣,第一种技术是处理它的最舒适的方法。
答案 2 :(得分:1)
在第一种情况下,派生类可以选择是否实现析构函数。 在第二种情况下,必须重写纯虚析构函数,因此派生类被强制实现析构函数。
除非你有什么理由要强制这样做,否则我会选择第一种情况。
答案 3 :(得分:1)
好的,找到了一个链接,所以我想提一下这个答案:
Are inline virtual functions really a non-sense?
我见过没有发出的编译器 任何v表,如果没有非内联函数 完全存在(并在一个中定义 实现文件而不是 标题然后)。他们会抛出错误 喜欢缺少vtable-for-class-A或 类似的东西,你会 像我一样混淆了地狱。
确实,这不符合 标准,但它发生如此考虑 至少放一个虚函数 不在标题中(如果只是虚拟 析构函数),这样编译器 可以为班级发出vtable 那个地方。我知道它发生了 某些版本的gcc。 (Johannes Schaub)
它与你的第二个案例略有不同(建议实际上完全从头文件中取出函数,以免成为gcc问题的受害者)但我想我会提到它。 gcc的怪癖偶尔会咬人。