有没有办法在构造函数代码而不是初始化列表中初始化类的成员对象?

时间:2018-12-26 22:30:02

标签: c++ memory constructor member

考虑一下,我想在对象中包装一些库代码。该库需要通过在包装类的构造函数中调用某些函数来建立和初始化。

然后,librarie的“对象”开始创建更多不同的“对象”,包装类以另一种包装对象的形式包装该对象,而包装对象应该是该类的普通成员。

但是据我所知,只能通过在构造函数的初始化列表中调用其构造函数来初始化或创建类的成员。这些代码的执行优先于实际类的构造函数,该类进行库及其环境的初始化,这使我无法实际将该成员对象初始化为成员,而是迫使我将其初始化为指向的指针。第二个包装器,因为它的构造函数必须在第一个构造器的代码内手动调用。

示例:

class A {
public:
    A() {
        if(!wrapped_library_init()) {
            exit(CRITICAL_ERROR);
        }
        ptr_to_some_library_metadata *a = library_function(); /*Needs to
        be called after wrapped_library_init() or needs a pointer to some
        wrapped object created inside this constructor */
        //initialize b
    }
private:
    B b; //Wants to be a member but can not
};

class B {
    B(ptr_to_some_library_metadata *a);
}

3 个答案:

答案 0 :(得分:3)

成员对象只能在成员初始化器列表中构造。但是,有几种技术可以用来初始化对象:

  1. 在返回合适的对象之前,使用辅助函数lambda进行必要的额外工作。例如:

    A()
          : B([]{
              if (!wrapped_library_init()) {
                  exit(CRITICAL_ERROR);
              }
              return library_function();
          }()) {
    }
    
  2. 您可以通过仅对适当的成员使用union来延迟构建。使用此技术时,需要明确销毁成员,例如:

    class A {
        union Bu { B b };
        Bu b;
    public:
        A() {
            if (!wrapped_library_init()) {
                exit(CRITICAL_ERROR);
            }
            new(&b.b) B(library_function());
        }
        ~A() {
            b.b.~B();
        }
        // ...
    };
    

我个人会使用第一种方法。但是,在某些情况下,使用union来延迟构造会有所帮助。

答案 1 :(得分:1)

那里有Initializer列表,可以使用默认构造函数以外的其他构造函数。

但是没有什么阻碍您创建可初始化b的自定义函数:

class A {
public:
    A():b(init()) {
    }
private:
    B b; //Wants to be a member but can not

    static B init()
    {
        if(!wrapped_library_init()) {
            exit(CRITICAL_ERROR);
        }
        ptr_to_some_library_metadata *a = library_function(); /*Needs to
        be called after wrapped_library_init() or needs a pointer to some
        wrapped object created inside this constructor */

        return B(a);
    }
};

答案 2 :(得分:0)

将您的库包装在一个类中:

class LibraryWrapper
{
public:
    LibraryWrapper()
    {
        if(!wrapped_library_init()) {
            exit(CRITICAL_ERROR);
        }
        lib_data.reset(library_function()); /*Needs to
        be called after wrapped_library_init() or needs a pointer to some
        wrapped object created inside this constructor */
    }
    //~LibraryWrapper() {/**/}
    //LibraryWrapper(const LibraryWrapper&) {/**/}            // =delete; ?
    //LibraryWrapper& operator=(const LibraryWrapper&) {/**/} // =delete; ?

//private: // and appropriate interface to hide internal
    std::unique_ptr<ptr_to_some_library_metadata, CustomDeleter> lib_data;
};

class B {
public:
    explicit B(ptr_to_some_library_metadata *a);
    // ...
};

并使用额外的成员或继承

class A
{
public:
    A() : b(lib.lib_data.get()) {}
private:
    LibraryWrapper lib; // placed before B
    B b;
};