使用没有堆分配的虚方法实例化类

时间:2016-08-11 01:22:30

标签: c++ c++11

class Base
{
public:
    virtual ~Base() {}
    virtual void Foo() = 0;
};

class FirstDerived: public Base
{
public:

    void Foo() { cout << "FirstDerived" << endl; }
};

class SecondDerived: public Base
{
public:

    void Foo() { cout << "SecondDerived" << endl; }
};

union PreallocatedStorage
{
    PreallocatedStorage() {}
    ~PreallocatedStorage() {}

    FirstDerived First;
    SecondDerived Second;
};

class ContainingObject
{
public:

    Base* GetObject()
    {
        if (!m_ptr)
        {
            // TODO: Make runtime decision on which implementation to instantiate.
            m_ptr = new(&m_storage) SecondDerived();
        }

        return m_ptr;
    }

    ~ContainingObject()
    {
        if (m_ptr)
        {
            m_ptr->~Base();
        }
    }

private:

    PreallocatedStorage m_storage;
    Base* m_ptr = nullptr;
};

int main()
{
    auto object = make_unique<ContainingObject>();

    // ...
    // Later, at a point where I don't want to make more heap allocations...
    // ...
    auto baseObject = object->GetObject();
    baseObject->Foo();

    return 0;
}

我想在这里实现的目标:

  • 我需要实例化一个具有虚方法的类。
  • 在这个时间点,我确切地知道要实例化哪个派生类,我无法进行进一步的堆分配(这只是出于好奇,所以确切原因不相关)。
  • 因此,我想以某种方式预先分配足够的空间来容纳任何可能的实现,然后决定我将在其中实例化哪个类。

上述代码中是否存在任何标准不合规/未定义的行为?

1 个答案:

答案 0 :(得分:0)

代码是正确的。请参阅有关该问题的评论,以获取一些有趣的见解,尤其是std::aligned_union的使用,该PreallocatedStorage可用作上述queue联合的通用替代。