6

如果我想避免它的实例,保护基类构造函数是一种好习惯吗?我知道我也可以有一个纯虚拟虚拟方法,但这似乎很奇怪......

请考虑以下代码:

#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

4 回答 4

9

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

但是,在基类中定义非纯虚函数并不被认为是好的做法,但在很大程度上取决于您的用例并且没有害处。

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

于 2013-09-30T09:18:31.183 回答
2

您想要实现的通常是通过析构函数而不是构造函数完成的,只是因为您可以使用该函数来引导您需要的行为,而不必使用您编写的每个新构造函数来处理它。这是一种常见的编码风格/指南,

  • 如果要允许该类的实例,请公开析构函数。通常这些类并不意味着继承自。
  • 如果您想在多态上下文中使用和删除该类但不想允许该类的实例,请使析构函数成为纯虚拟和公共的。换句话说,对于多态删除的基类。
  • 如果您不想允许类的实例并且不想以多态方式删除其派生类,则使析构函数成为非虚拟和受保护的。通常,您根本不想多态地使用它们,即它们没有虚函数。

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

于 2013-09-30T10:22:42.167 回答
1

它可以满足您的要求。

但是,我不确定您从中获得了什么。有人可以写

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

通常,并不是在基类中添加无意义的纯虚函数……而是存在纯虚函数,在基层无法为其提供有意义的实现,这就是它们最终成为纯虚函数的原因。

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

于 2013-09-30T09:14:06.643 回答
1

使析构函数成为纯虚拟的。每个类都有一个析构函数,而基类通常应该有一个虚拟析构函数,所以你不会添加一个无用的虚拟函数。

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

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

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

于 2013-09-30T09:28:22.637 回答