我想知道是否可以将一个类分配给特定的成员数据并创建该类的实例

时间:2018-08-22 04:59:12

标签: c++

我想知道是否有可能。

我在一个项目中上了一堂课。

    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类。 可能吗??

谢谢您的回复!

1 个答案:

答案 0 :(得分:4)

如评论中所述:

  1. 您不想让A为模板类。
  2. 您要创建实例实例的类共享一个公共基类,这也是成员指针的类型(以下条件的前提!)。

因此,您可以将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>();
}

我认为这是可以接受的,因为您 能够以某种方式告诉您您实际要创建哪种类型。

对于不同的类(createInternalBcreateInternalC)来说,替代方法是使用不同的函数,但这当然不太优雅。

旁注:

  

有可能吗?

即使您的类没有共享通用的基类,您仍然可以将创建的对象存储在std::variant中,或者,如果碰巧编译了C ++ 11之前的版本,即使在工会中也是如此(但您需要注意实际存储的是哪种类型–在这方面,std::variant更加安全,因此请尽可能使用它。)

更新新评论:

如果您希望能够在A中创建任意对象而不必知道实际创建了哪个对象,现在可以提供另外两种选择:

在第一个变体中,您可以在A中使createInternal虚拟(甚至可能是纯虚拟),然后在派生类中进行覆盖以提供适合您需求的对象。

在第二个变体中,您提供了一些对象提供程序类的实例;假设DB : public DA : 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,如果不是)摘要)。