我敢肯定,这是一个非常简单的问题。 下面的代码显示了我想要做的事:
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
使用new
,但我希望有一个更简单的方法。
编辑:我刚才已说过,但我的实际问题有一个额外的复杂性:我需要初始化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前一个struct
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)) {
}
};
这将调用do_something()
初始化之前m_class
。 请注意,你不能调用非静态成员函数MyClass
构造函数初始化列表完成之前。 该功能必须是它的基类的成员,基类的构造函数必须已完成该工作。
还要注意的是功能,当然,总是叫,为每个创建单独的对象 - 不仅为创建的第一个对象。 如果你想这样做,你可以创建初始化的构造函数内的静态变量:
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)) {
}
};
它使用逗号操作符。 请注意,您可以通过赶上抛出的异常do_something
使用功能try块
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 */ }
};
该do_something
功能将再次下一次调用,如果把它扔到引起的那个异常MyClass
对象不能被创建。 希望这可以帮助 :)
使用初始化列表语法:
class MyClass {
public:
MemberClass m_class;
MyClass(int xyz) : m_class(xyz == 42 ? MemberClass(12) : MemberClass(32)
/* see the comments, cleaner as xyz == 42 ? 12 : 32*/)
{ }
};
也许吸尘器工厂:
MemberClass create_member(int x){
if(xyz == 42)
return MemberClass(12);
// ...
}
//...
MyClass(int xyz) : m_class(create_member(xyz))
MyClass(int xyz) : m_class(xyz==42 ? 12 : 32) {}
要回答你的修订问题,即变得有点棘手。 最简单的方法是使m_class
的指针。 如果你真的想把它当作一个数据成员,那么你必须得到创造性。 创建一个新的类(如果它定义内部MyClass的是最好的)。 有它的构造函数是需要被调用的函数。 第一个数据成员的声明(这将使其第一instaniated)中包含它。
class MyClass
{
class initer { public: initer() {
// this must happen before m_class is created
do_something();
}
}
initer dummy;
public:
MemberClass m_class;
MyClass(int xyz) : m_class(xyz==42? 12 : 43)
{
// dummy silently default ctor'ed before m_class.
}
};
要么:
class MemberClass {
public:
MemberClass(int abc){ }
};
class MyClass {
public:
MemberClass* m_class;
MyClass(int xyz) {
if(xyz == 42)
m_class = new MemberClass(12);
else
m_class = new MemberClass(32);
}
};
如果你不知何故仍然要保持相同的语法。 会员initalization是更有效的,但。
试试这个:
class MemberClass
{
public:
MemberClass(int abc = 0){ }
};
这使得它的默认值,并且您的默认构造函数。
有初始化发生其他的事情发生后,你确实需要使用指针,是这样的:
class MyClass {
public:
MemberClass * m_pClass;
MyClass(int xyz) {
do_something(); // this must happen before m_class is created
if(xyz == 42)
m_pClass = new MemberClass(12);
else
m_pClass = new MemberClass(32);
}
};
唯一的区别是,你需要访问成员变量m_pClass->counter
,而不是m_class.counter
,并delete m_pClass
在析构函数。