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

Protected constructor to make base class not instantiable

本文关键字:实例化 基类 构造函数 受保护      更新时间:2023-10-16

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

请考虑以下代码:

#include <iostream>
using std::cout;
using std::endl;
class A 
{
protected:
    A(){};
public:
    virtual void foo(){cout << "An";};
};
class B : public A
{
public:
    void foo(){cout << "Bn";}
};
int main()
{
    B b;
    b.foo();
    A *pa = new B;
    pa->foo();
    // this does (and should) not compile:
    //A a;
    //a.foo();
    return 0;
}

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

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

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

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

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

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

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

它按照你的要求去做。

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

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

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

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

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

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

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

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