防止头文件之外的子类

Ahm*_*d A 11 c++ inheritance c++11

我在.h文件中定义了以下三个类:

class Base
{ // number of pure virtual functions };

class Derived1 : public Base
{ // number of pure virtual functions };

class Derived2 : public Base
{ // number of pure virtual functions };
Run Code Online (Sandbox Code Playgroud)

我希望此头文件的用户只能继承Derived1或Derived2.我想阻止用户继承Base.我"可以"为类Base使用关键字"final",但这会阻止我在头文件中进行子类化.我需要在头文件中包含所有上述类,因为用户需要提供Base和DerivedX类中方法的定义.

我正在考虑将继承范围限制在头文件中(类似于静态变量).任何建议或想法将不胜感激.

Mar*_* A. 17

您可以将Base构造函数设为私有,并让这两个类成为朋友,例如

#include <iostream>

class Base
{
private:
    Base() {}
    friend class Derived1;
    friend class Derived2;
};

class Derived1 : public Base
{
};

class Derived2 : public Base
{
};

int main() {

    Derived1 obj;
    Base obj2; // Error

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

http://ideone.com/NUWad0

另请注意:基类的复制/移动构造函数可能也应该是私有的.我没有添加代码来关注主要提案,但你也应该考虑一下.


关于朋友构造函数进行编辑.

首先:在编译器看到它的定义之前,你不能引用不完整类型的成员(它可以作为一次性传递,并且可能涉及一些重载决策).这意味着以下内容不起作用:

class Derived1;
class Derived2;

class Base
{
private:
    Base() {}
    friend Derived1::Derived1(); // Error - incomplete type 'Derived1' in nested name specifier
};

class Derived1 : public Base
{
    public:
    Derived1() {};
};

...    
Run Code Online (Sandbox Code Playgroud)

并且你不能转发声明一个基类(你不知道为派生对象分配多少空间):

class Base;

class Derived1 : public Base // Error: base class has incomplete type
{
    public:
    Derived1() {};
};

class Base
{
private:
    Base() {}
    friend Derived1::Derived1();
};

...
Run Code Online (Sandbox Code Playgroud)

因此,在您的特定情况下,您最好使用朋友类访问,除非您想要修改设计中的某些内容.

  • 我也是这样做的.只是注意,我会删除`using namespace std`,因为这是不好的做法,并且无论如何都不会在这段代码中做任何事情. (5认同)
  • @omid这是正确的,我只是试了一下.我可以定义"class Derived3:public Base {};".如果编译器有/可能已将此标记为错误,我会喜欢它.但是,如果我尝试实例化Derived3,编译器会生成错误.我想这很好. (3认同)