将抽象类(仅纯虚函数)的继承/派生限制到某个类

Limit inheritance/derivation of an abstract class (only pure virtual functions) to a certain class

本文关键字:派生 继承 抽象类 函数      更新时间:2023-10-16

给定一个抽象类AbstractParentPrinter(即具有一个纯虚函数):

class AbstractParentPrinter {
public:
  virtual void print() = 0;
};

AbstractPrinterAbstractParentPrinter的一个(抽象)子类:

template<typename T, typename = std::enable_if<std::is_base_of<AbstractPrinterStore, T>::value>>
class AbstractPrinter : public AbstractParentPrinter {
protected:
  T& getPrinterStore() {
        return printerStore;
    }
private:
  static T printerStore;
};
template<typename T>
T AbstractPrinter <T>::printerStore;

PrinterAAbstractPrinter<PrinterStoreA>的一个子类。PrinterStoreAAbstractPrinterStore的子类(未显示)。

class PrinterA : public AbstractPrinter<PrinterStoreA> {
public:
  void print() {
   // Do something with PrinterStoreA and print
   // An AbstractPrinterStore here instead would be not sufficient
   std::cout << "Printer A has printed!" << std::endl; 
  }
};

由于AbstractPrinter<T>(与AbstractParentPrinter合并)不能存储在std::vector中,因此我为此目的创建了一个父类AbstractPrinter。除了AbstractPrinter之外,如何防止AbstractParentPrinter的派生?

你可以把最基本类的构造函数设为private,然后把你想从它派生的类设为友类。

class AbstractParentPrinter
{
    private: AbstractParentPrinter()
    {}
    template<typename t> friend class AbstractPrinter;
};

另一种方法是限制类的任何使用(不仅仅是继承),例如使用匿名命名空间或使其成为嵌套类。

====对标题中问题的简单一般答案在这里结束====

在您的情况下,可以考虑更改结构以使用非虚拟接口模式。您将创建一个可以保存在vector中的非模板类,它将拥有一个指向模板化版本之一的指针。这是pImpl模式的一个用法。
class AbstractParentPrinter;
class Printer
{
    AbstractParentPrinter* pImpl;

    public:
    void print();
    //add some constructor code/declaration to initialise pImpl to the correct template      
};

您可以在Printer中嵌套AbstractParentPrinter,或者像上面那样向前声明它。如果嵌套它,可以使用std::unique_ptr,否则将在printer的析构函数中删除它。

class AbstractParentPrinter
{
    public: virtual void print() = 0;
};
// insert the template definitions here if you like
void Printer::print()
{
    pImpl->print();
}

模板甚至可以放在同一个cpp中(是的,cpp中的模板-通常必须将它们放在头文件中的全部要点是使其他代码可以访问它们,但我假设你的问题的动机是隐藏这些实现细节)

你仍然有你原来的基类和实现print的模板,但是现在你有了一个额外的非抽象的,非模板的Printer类,但是拥有这个类还有其他好处。你的消费代码不需要知道抽象类和模板——它可以有一个Printer的向量,它不需要处理指向Printer的指针,这样可以更容易地管理Printer对象的生命周期。Printer类创建的额外层还可以将调用代码与各种打印类实现中的更改隔离开来。