我想知道是否有可能。
我在一个项目中上了一堂课。
class A { ...
void CreateInternal(void);
B* m_pData;
... }
void A::CreateInternal(void)
{
m_pData= new B;
}
在其他项目中,我添加了C类,并希望像这样在A :: CreateInernal(void)中创建它。
void A::CreateInternal(void)
{
m_pData = new C; // ex) B is base class of C
}
当然,我可以将A类转换为模板类,但是我不想要它。我想最后用它。 (假设依赖项或其他构建错误是免费的)
typename<class T>
class A { ...
void CreateInternal(void);
T* m_pData
... }
void A<T>::CreateInternal(void)
{
m_pData = new T;
}
我只想在A类中注册B类或C类。 可能吗??
谢谢您的回复!
答案 0 :(得分:4)
如评论中所述:
因此,您可以将createInternal
用作模板函数:
template <typename T>
void A::createInternal()
// ^^^ A still is a normal class!
{
m_data = new T();
// (will fail if T is a different type NOT inheriting
// from the base class in question)
}
旁注:通常,如果类中提供了模板函数,则如果createInstance
是 private,则必须implement them in the header file(通常至少有办法...) ,但是您不要从公共内联函数中调用它,您可以在源文件中安全地实现它,并且此文件将成为模板使用过的唯一位置
您甚至可以更进一步,并允许使用可变参数模板调用 all 所有可能的构造函数:
template <typename T, typename ... TT>
void A::createInternal(TT&& ... tt)
{
m_data = new T(std::forward(tt)...);
// (will fail, if there is no matching constructor
// for the arguments provided)
}
好,您现在必须指定要创建的实例:
void A::f()
{
createInternal<B>();
createInternal<C>();
}
我认为这是可以接受的,因为您 能够以某种方式告诉您您实际要创建哪种类型。
对于不同的类(createInternalB
,createInternalC
)来说,替代方法是使用不同的函数,但这当然不太优雅。
旁注:
有可能吗?
即使您的类没有共享通用的基类,您仍然可以将创建的对象存储在std::variant
中,或者,如果碰巧编译了C ++ 11之前的版本,即使在工会中也是如此(但您需要注意实际存储的是哪种类型–在这方面,std::variant
更加安全,因此请尽可能使用它。)
更新新评论:
如果您希望能够在A中创建任意对象而不必知道实际创建了哪个对象,现在可以提供另外两种选择:
在第一个变体中,您可以在A中使createInternal
虚拟(甚至可能是纯虚拟),然后在派生类中进行覆盖以提供适合您需求的对象。
在第二个变体中,您提供了一些对象提供程序类的实例;假设D
是B : public D
和A : public D
的基类,那么解决方案可能类似于以下内容:
class A
{
public:
class ObjectProvider
{
public:
virtual ~ObjectProvider() = default;
public: virtual D* createInstance() = 0;
};
template <typename T>
class TheObjectProvider : public ObjectProvider
{
public:
D* createInstance() override
{
return new T();
}
};
A(std::unique_ptr<ObjectProvider> p)
: objectProvider(std::move(p))
{ }
private:
std::unique_ptr<ObjectProvider> objectProvider;
std::unique_ptr<D> m_data;
void createInternal()
{
m_data = objectProvider->createInstance();
}
};
用法:
A ab(std::make_unique<A::ObjectProvider<B>());
// your own custom object provider:
class OP : public A::ObjectProvider
{
public:
C* createInstance() override { return new C(); }
};
A ac(std::make_unique<OP>());
std::unique_ptr
作为参数(尽管通常不建议使用智能指针)现在具有一个重要功能:它指示该类将对传递的对象(即i)拥有所有权。 e。是赫伯·萨特(Herb Sutter)措辞的沉沦–请参阅他的GotW91)。
如果您拥有最常用的数据类型(例如B
),则可以提供一个重载的默认构造函数,为该类型提供对象提供程序(或者可能是基本类型D
,如果不是)摘要)。