给定是一个抽象类AbstractParentPrinter
(即具有纯虚函数):
class AbstractParentPrinter {
public:
virtual void print() = 0;
};
AbstractPrinter
是AbstractParentPrinter
的一个(抽象)子类:
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;
PrinterA
是AbstractPrinter<PrinterStoreA>
的子类。 PrinterStoreA
是AbstractPrinterStore
的子类(未显示)。
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
。除了AbstractParentPrinter
之外,如何阻止来自AbstractPrinter
的推导?
答案 0 :(得分:2)
你可以将你最基本的类的构造函数设为私有,然后让你想从它派生的类成为它的朋友。
class AbstractParentPrinter
{
private: AbstractParentPrinter()
{}
template<typename t> friend class AbstractPrinter;
};
另一种方法是限制对类的任何使用(不仅仅是继承),例如使用匿名命名空间或使其成为嵌套类。
====标题中简单的一般案例答案如标题所示====
在您的情况下,可能会考虑更改结构以便使用非虚拟接口模式。您将创建一个非模板类,您可以将其保存在向量中,该类将拥有指向其中一个模板化版本的指针。它是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,否则你将在打印机的析构函数中删除它。
在cpp
中class AbstractParentPrinter
{
public: virtual void print() = 0;
};
// insert the template definitions here if you like
void Printer::print()
{
pImpl->print();
}
模板甚至可以放在同一个cpp中(cpp中的yes模板 - 通常必须将它们放在头文件中的全部内容是让它们可以被其他代码访问,但我假设你的问题的动机是隐藏这些实现细节)
因此,您仍然拥有原始基类和实现打印的模板,但现在您已经拥有了一个额外的非抽象非模板打印机类,但是拥有该类还有其他好处。您的消费代码不需要知道抽象类和模板 - 它可以只有一个打印机向量,它不需要处理指向打印机的指针,这样可以更轻松地管理打印机对象的生命周期。 Printer类创建的额外层也可以将调用代码与各种打印类的实现中的更改隔离开来。