我想知道这是否可能。
我在一个项目中有一个类。
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 类。 可能吗??
感谢您的回复!
如注释中所述:
- 您不想使 A 成为模板类。
- 要创建实例的类共享一个公共基类,这也是成员指针的类型(以下前提条件!
因此,您可以将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
是私有的,但是,并且您不从公共内联函数调用它,则可以安全地在源文件中实现它,并且此文件将是使用该模板的唯一位置。
您甚至可以更进一步,允许使用可变参数模板调用所有可能的构造函数:
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
中创建的对象,或者,如果你碰巧编译了 pre-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
as 参数(尽管通常不建议使用 smart 指针(现在有一个重要的功能:它表示类将获得传递对象的所有权,即 Herb Sutter 措辞中的一个接收器 - 参见他的 GotW91(。
如果您有最常用的数据类型(例如B
(,您可以提供一个重载的默认构造函数,为此类型提供对象提供程序(或者可能是基类型D
,如果不是抽象的(。