正确地初始化C ++成员变量的正确方法? [英] Right way to conditionally initialize a C++ member variable?

查看:115
本文介绍了正确地初始化C ++成员变量的正确方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我确定这是一个非常简单的问题.以下代码显示了我正在尝试做的事情:

I'm sure this is a really simple question. The following code shows what I'm trying to do:

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是用空构造函数创建的(不存在).正确的做法是什么?我的猜测是使用指针,并使用new实例化m_class,但我希望有一种更简单的方法.

This doesn't compile, because m_class is being created with an empty constructor (which doesn't exist). What is the right way of doing this? My guess is using pointers and instantiating m_class using new, but I'm hoping there is an easier way.

我应该早先说过,但是我的实际问题还有一个额外的麻烦:我需要在初始化m_class之前调用一个方法,以设置环境.因此:

I should have said earlier, but my actual problem has an additional complication: I need to call a method before initializing m_class, in order to set up the environment. So:

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);
    }
};

是否可以通过精美的初始化列表技巧来实现这一目标?

Is it possible to achieve this with fancy initialization list tricks?

推荐答案

使用条件运算符.如果表达式较大,请使用函数

Use the conditional operator. If the expression is larger, use a function

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

To call a function before initializing m_class, you can place a struct before that member and leverage 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必须已经完成才能正常工作.

This will call do_something() before initializing m_class. Note that you are not allowed to call non-static member functions of MyClass before the constructor initializer list has completed. The function would have to be a member of its base class and the base class' ctor must already be completed for that to work.

还请注意,对于创建的每个单独对象,当然总是调用该函数-不仅是针对创建的第一个对象.如果要这样做,可以在初始化程序的构造函数中创建一个静态变量:

Also note that the function, of course, is always called, for each separate object created - not only for the first object created. If you want to do that, you could create a static variable within the initializer's constructor:

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块

It's using the comma operator. Note that you can catch any exception thrown by do_something by using a function-try block

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对象失败的异常,则下次将再次调用该函数.希望这会有所帮助:)

The do_something function will be called again next time, if it threw that exception that caused the MyClass object fail to be created. Hope this helps :)

这篇关于正确地初始化C ++成员变量的正确方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆