我相信这是一个非常简单的问题.以下代码显示了我要做的事情:
class MemberClass { public: MemberClass(int abc){ } }; class MyClass { public: MemberClass m_class; MyClass(int xyz) { if(xyz == 42) m_class = MemberClass(12); else m_class = MemberClass(32); } };
这不会编译,因为m_class正在使用一个空构造函数(不存在)来创建.这样做的正确方法是什么?我的猜测是使用指针和实例化m_class使用新的,但我希望有一个更简单的方法.
编辑:我应该早点说过,但我的实际问题有一个额外的复杂性:我需要调用一个方法,然后初始化m_class,以便设置环境.所以:
class MyClass { public: MemberClass m_class; MyClass(int xyz) { do_something(); // this must happen before m_class is created if(xyz == 42) m_class = MemberClass(12); else m_class = MemberClass(32); } };
有可能通过花哨的初始化列表技巧来实现这一点吗?
解决方法
使用条件运算符.如果表达式较大,请使用函数
class MyClass { public: MemberClass m_class; MyClass(int xyz) : m_class(xyz == 42 ? 12 : 32) { } }; class MyClass { static int classInit(int n) { ... } public: MemberClass m_class; MyClass(int xyz) : m_class(classInit(xyz)) { } };
要在初始化m_class之前调用函数,可以在该成员之前放置一个结构体并利用RAII
class MyClass { static int classInit(int n) { ... } struct EnvironmentInitializer { EnvironmentInitializer() { do_something(); } } env_initializer; public: MemberClass m_class; MyClass(int xyz) : m_class(classInit(xyz)) { } };
这将在初始化m_class之前调用do_something().请注意,在构造函数初始化程序列表完成之前,不允许调用MyClass的非静态成员函数.该函数必须是其基类的成员,并且基类“ctor”必须已经完成才能使其工作.
还要注意的是,对于每个单独的对象,这个函数当然总是被调用,而不仅仅是创建的第一个对象.如果要这样做,可以在初始化程序的构造函数中创建一个静态变量:
class MyClass { static int classInit(int n) { ... } struct EnvironmentInitializer { EnvironmentInitializer() { static int only_once = (do_something(),0); } } env_initializer; public: MemberClass m_class; MyClass(int xyz) : m_class(classInit(xyz)) { } };
它使用逗号运算符.请注意,您可以使用function-try块捕获do_something抛出的任何异常
class MyClass { static int classInit(int n) { ... } struct EnvironmentInitializer { EnvironmentInitializer() { static int only_once = (do_something(),0); } } env_initializer; public: MemberClass m_class; MyClass(int xyz) try : m_class(classInit(xyz)) { } catch(...) { /* handle exception */ } };