加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

有条件地初始化C成员变量的正确方法?

发布时间:2020-12-16 05:38:49 所属栏目:百科 来源:网络整理
导读:我相信这是一个非常简单的问题.以下代码显示了我要做的事情: 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 = MemberClas
我相信这是一个非常简单的问题.以下代码显示了我要做的事情:
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 */ }
};

do_something函数将被下次再次调用,如果它抛出引起MyClass对象失败的异常.希望这可以帮助 :)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读