C ++:如何在对象构造期间在初始化列表之外调用成员构造函数?

时间:2018-07-13 07:52:59

标签: c++ oop constructor initializer-list

我想在所有者构造函数中调用成员对象的构造函数,但是由于依赖关系而无法在初始化列表中构造成员对象。初始化后如何调用构造函数?我真的很想不使用init方法

4 个答案:

答案 0 :(得分:5)

您不能在初始化列表之外调用成员类的构造函数。

PS:即使您自己没有在初始化程序列表中调用它,编译器也会隐式执行它。


如果无法在初始化列表中调用它,并且不想使用类似init的方法,请重新考虑您的设计/方法。

答案 1 :(得分:3)

您有两种选择:要么使用动态存储,要么使用新的放置。

第一个显而易见(如注释中所指出,您可以使用unique_ptr)。如果要避免这种情况,可以尝试使用std::aligned_union作为存储的新放置位置:

class SomeClass { ... };

class Owner
{
public:
    Owner()
    {
        m_ptr = new(&m_storage) SomeClass();
    }

    ~Owner()
    {
         m_ptr->~SomeClass();
    } 

private:
    std::aligned_union<0, SomeClass> m_storage;
    SomeClass* m_ptr;
};

注意:在这种情况下,您有责任调用对象的析构函数,如上所示。

您可以用m_ptr(用已删除的内容仅调用析构函数)包装unique_ptr来避免这种情况:

struct DtorDeleter 
{ 
    template<typename T>
    void operator ()(T* ptr) { ptr->~T(); } 
};

std::unique_ptr<SomeClass, DtorDeleter> m_ptr; // no need to call destructor manually

答案 2 :(得分:0)

您可以为此使用联合(需要C ++ 11):

#include <new>

class Foo {
    public:
        Foo(int a) { }
};

class Bar {
    public:
        Bar() {
            new(&m_foo) Foo(42); // call the constructor
            // you can use m_foo from this point
        }

        ~Bar() {
            m_foo.~Foo(); // call the destructor
        }

    private:
        union { // anonymous union
            Foo m_foo;
        };
};

请注意,您需要在m_foo处显式调用~Bar()的析构函数。

答案 3 :(得分:0)

想在所有者构造函数中调用成员对象的构造函数,但由于依赖关系而无法在初始化列表中构造成员对象

您可以修改您的类以具有正确的依赖关系顺序,并可以使用委派构造函数:

转身:

struct S
{
    S(/*..*/) : /*m1(data), m2(data),*/ data(/*..*/) // Issue, m1, m2 constructed before data
    {
        ComplexData2 data2 = Query();

        m1.init(data, data2.someField1); // Doesn't like init method
        m2.init(data, data2.someField2); // Doesn't like init method
    } 

    Member1 m1; // Cannot be const with init method :/
    Member2 m2; // Cannot be const with init method :/
    ComplexData data;
};

进入

struct S
{
    S(/*..*/) : S(Query() /*, ..*/) {}

// private: // probably private
    S(const ComplexData2& data2 /*, ..*/) :
        data(/*..*/),
        m1(data, data2.someField1),
        m2(data, data2.someField2)
    {
    } 

public:
    ComplexData data; // Before m1, m2 for dependencies.
    /*const*/ Member1 m1; // Can be const
    /*const*/ Member2 m2; // Can be const
};