受保护的构造函数,使基类不可实例化

时间:2013-09-30 09:08:02

标签: c++ inheritance constructor virtual-functions

如果我想避免它的实例,是否保护基类构造函数是一种好习惯?我知道我可以使用纯虚拟虚拟方法,但这看起来很奇怪......

请考虑以下代码:

#include <iostream>

using std::cout;
using std::endl;

class A 
{
protected:
    A(){};
public:
    virtual void foo(){cout << "A\n";};
};

class B : public A
{
public:
    void foo(){cout << "B\n";}
};

int main()
{
    B b;
    b.foo();
    A *pa = new B;
    pa->foo();

    // this does (and should) not compile:
    //A a;
    //a.foo();
    return 0;
}

我有没有看到缺点或副作用?

4 个答案:

答案 0 :(得分:4)

通常的做法是使基类构造函数受到保护。当你的基类中有一个纯虚函数时,这不是必需的,因为你无法实例化它。

但是,在基类中定义非纯虚函数不被视为良好实践,但在很大程度上取决于您的用例并且不会造成损害。

没有任何不利或副作用。使用受保护的构造函数,您只需告诉其他开发人员您的类仅用作基础。

答案 1 :(得分:2)

您想要实现的通常是通过析构函数而不是构造函数来完成,因为您可以使用该函数控制所需的行为,而不必使用您编写的每个新构造函数来处理它。

是一种常见的编码风格/指南
  • 如果要允许类的实例,则将析构函数设置为public。通常这些类不应该继承自。
  • 如果要在多态上下文中使用和删除类但不想允许该类的实例,则使析构函数变为纯虚拟和公共。换句话说,对于多态删除的基类。
  • 如果您不想允许类的实例并且不希望以多态方式删除其派生,则使析构函数成为非虚拟和受保护的。通常,您根本不希望使用多态,即它们没有虚函数。

您选择后两者中的哪一项是设计决定,无法从您的问题中回答。

答案 2 :(得分:1)

它可以满足您的要求。

但是我不确定你用它获得了什么。有人可以写

struct B : A {
   // Just to workaround limitation imposed by A's author
};

通常情况下,不是将无意义的纯虚函数添加到基类中......而是存在纯虚函数,其基本级别无法提供有意义的实现,这就是为什么它们最终成为纯虚函数的原因。

无法实例化该类是一个很好的额外属性。

答案 3 :(得分:0)

使析构函数纯粹虚拟。每个类都有一个析构函数,基类通常应该有一个虚析构函数,因此你不会添加一个无用的虚函数。

请注意,纯虚拟析构函数必须具有函数体。

class AbstractBase
{
public:
    virtual ~AbstractBase() = 0;
};
inline AbstractBase::~AbstractBase() {}

如果您不希望将析构函数体放在头文件中,请将其放在源文件中并删除内联关键字。