C++在类构造函数中定义常量成员变量

15 c++ constructor initialization constants

通常当你的类中有一个常量私有成员变量时,它只有一个getter但没有setter,它看起来像这样:

// Example.h
class Example {
    public:
        Example(const int value);
        const int getValue() const;
    private:
        const int m_value;
};


// Example.cpp
#include "Example.h"

Example::Example(const int value)
: m_value(value)
{
}

const int Example::getValue() const
{
    return m_value;
}
Run Code Online (Sandbox Code Playgroud)

现在我正在尝试做的是,有一个像这样的常量int成员变量,而不是在初始化部分中定义它,如下所示:: m_value(value)我需要采取另一个对象 - 我将在此示例中使用向量 - as构造函数的参数,并根据参数对象设置m_value.在这种情况下,如果大小超过0,我将尝试执行向量大小+ 1.所以这就是我所做的:

Example::Example(std::vector<Example*> myVec)
{
    if (myVec.size()) {
        m_value = myVec.size() + 1;
    }
    else {
        m_value = -1;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我得到一个错误uninitialized member 'Example::m_value' with 'const' type 'const int',如果我在初始化部分初始化m_value,我得到的错误assignment of read-only data-member 'Example::m_value'对我来说都是有意义的,我应该得到那些错误,但我怎么能绕过它们呢?

编辑:我可以编辑的唯一方法m_value是在对象本身内部(因为m_value是私有的).只有getter会限制我将m_value设置为除了在构造函数中设置的内容以外的任何内容.将常量int作为成员变量有什么好处?

Omn*_*ous 30

使用一个静态成员函数compute得到你需要的结果并在初始化列表中调用该函数.像这样:

// Example.h
class Example {
    public:
        Example(const int value);
        Example(std::vector<Example*> myVec);

        const int getValue() const;
    private:
        const int m_value;

        static int compute_m_value(::std::vector<Example*> &myVec);
};

// Example.cpp
#include "Example.h"

Example::Example(const int value)
: m_value(value)
{
}

Example::Example(std::vector<Example*> myVec)
: m_value(compute_m_value(myVec))
{
}

const int Example::getValue() const
{
    return m_value;
}

int Example::compute_m_value(::std::vector<Example*> &myVec)
{
    if (myVec.size()) {
        return myVec.size() + 1;
    }
    else {
        return -1;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种特殊情况下,函数非常简单,只需: m_value(myVec.size() > 0 ? int(myVec.size() + 1) : int(-1)在构造函数中使用三元运算符(aka )直接计算初始化时的值.这看起来像一个例子,所以我给了你一个解决这个问题的非常通用的方法,即使计算你需要的答案的方法可能非常复杂.

一般问题是必须在初始化列表中初始化常量成员变量(以及引用过程为BTW的成员变量).但是初始化器可以是表达式,这意味着它们可以调用函数.由于这个初始化代码非常特定于类,因此它应该是类的私有(或可能是受保护的)函数.但是,因为在构造类之前调用​​它来创建一个值,它不能依赖于一个类实例存在,因此没有this指针.这意味着它需要是一个静态成员函数.

现在,类型myVec.size()std::vector<Example*>::size_t,并且该类型是无符号的.你使用的是-1的哨兵值,但事实并非如此.并且你把它存放在一个int可能不适合容纳它的大小.如果你的矢量很小,这可能不是问题.但是,如果您的矢量基于外部输入获取大小,或者您不知道它将获得多大,或任何其他因素,这将成为一个问题.您应该考虑这一点并相应地调整您的代码.

  • +1用于解决一般问题,并提供清晰的解释。 (2认同)

Pet*_*ker 5

首先,该变量定义在类定义,而不是在构造函数中.它在构造函数初始化.

其次,这样做的方式就像你的构造函数当前所做的那样:从初始化程序列表中存储它的值:

Example::Example(std::vector<Example*> myVec)
    : m_value(myVec.size() ? myVec.size() + 1 : -1) {
}
Run Code Online (Sandbox Code Playgroud)