关于C#:有条件地构造没有默认构造函数的成员对象

Constructing member objects without default constructor conditionally

我想有条件地构造没有默认构造函数的类成员。
基本上我想在类构造函数中执行以下操作:

1
2
3
4
5
6
7
class X{
public:
    X(Config config) {
        if (config.getBool) memberA("yes");
        else memberA("no");
    }
}

问题在于,如前所述,memberA 类没有默认构造函数,因此编译器无法构造它,从而导致错误。
显然我可以这样做:

1
2
3
4
5
6
class X{
public:
    X(Config config) : memberA("yes") {
    if (!config.getBool) memberA = MemberAClass("no");
    }
}

但我想知道是否有一种方法可以使用 if 子句构造成员,但不调用构造函数两次,以防止类的静态成员产生副作用。

更新:我忘了提到我实际上需要两个参数,但原理仍然有效:

1
X::X(Config cfg):member(cfg.getBool()?"yes":"no",cfg.getBool()?1:2){};


您必须使用构造函数初始化列表和条件运算符(而不是 if),如下所示:

1
2
X::X(const Config& config) : memberA(config.getBool() ?"yes" :"no")
{}

或创建一个函数来计算正确的参数:

1
2
3
4
5
6
7
const char* compute_memberA_arg(const Config& config) {
    if (config.getBool()) { return"yes"; }
    else { return"no"; }
}

X::X(const Config& config) : memberA(compute_memberA_arg(config))
{}

鉴于更新,我建议使用(静态)辅助方法:

1
2
3
4
MemberType X::initMemberA(bool flag) {
  return flag ? MemberType("yes", 1) : MemberType("no", 2);
}
X::X(Config cfg) : memberA(initMemberA(cfg.getBool())) { }

这是 C 的主要缺陷之一,您不能将成员的构造嵌入到构造函数代码中。当您需要根据参数使用不同的构造函数时,这尤其令人讨厌。在这些情况下,最好的解决方法是将成员的初始化(部分)移动到 init() 函数中。然后你可以做这样的事情:

1
2
3
4
5
6
7
8
9
10
11
class Foo {
    Bar bar;
public:
    Foo(bool flag) {
        if(flag) {
            bar.init("init from string");
        } else {
            bar.init(3, 7, 5);
        }
    }
};