【问题标题】:What is the point of non-static const data member? [duplicate]非静态 const 数据成员有什么意义? [复制]
【发布时间】:2014-11-03 17:59:13
【问题描述】:

对于以下代码:

class A
{
public:
    const int cx = 5;
};

在这里,将为 A 的每个对象创建一个 cx 的实例。这对我来说似乎是一种浪费,因为 cx 永远无法修改。实际上,我看不出编译器不应该强制将 const 数据成员设为静态的任何理由。谁能给我解释一下?

【问题讨论】:

  • 可能有 RAII 应用程序...
  • 这就像说编译器应该坚持所有静态数据都是恒定的。有些人喜欢他们的成员保持不变
  • 您仍然可以添加其他构造函数以使cx具有不同的值。
  • std::map 的值类型是 std::pair<const key_type, mapped_type>,因此具有非静态 const 成员。
  • 在这个人为的例子中是一种浪费。但总的来说,const 成员没有理由对所有对象都具有相同的值。

标签: c++ static constants


【解决方案1】:

一个 const 数据成员不必对所有实例都相同。你可以在构造函数中初始化它。

class A
{
public:
    A(int n) :cx(n) {}

    const int cx;
};

int main()
{
    A a1(10);
    A a2(100);
}

【讨论】:

  • 需要注意的是,您必须在初始化列表中对其进行初始化。当你进入构造函数的主体时,为时已晚。即失败:A(int n) { cx = n; }
【解决方案2】:

实际上,我看不出编译器不应该强制执行的任何理由 一个 const 数据成员静态。

您是否考虑过 cx 可能在构造函数中使用运行时已知的值进行初始化 - 并且在 A 的不同实例之间变化?
const 成员无法对其进行分配,但有时拥有无法更改其初始值的成员会很有用。

绝对不是最好的例子,但为了说明这个想法:

struct Multiplier
{
    const int factor;

    Multiplier(int factor) : factor(factor) {}

    int operator()( int val ) const
    {
        return val * factor;
    }
};

std::vector<int> vec{1, 2, 3};
std::vector<int> vec2;

int i;
std::cin >> i;

std::transform( std::begin(vec), std::end(vec),
                std::back_inserter(vec2), Multiplier(i) );

// vec2 contains multiples of the values of vec

【讨论】:

    【解决方案3】:

    如果值是用常量初始化的,如您的示例所示, 最好是静态的。但这并不总是 案子;经常有类似的东西:

    class Matrix
    {
        const int myRowCount;
        const int myColumnCount;
        std::vector<double> myData;
        //  ...
    public:
        Matrix( int rows, int columns )
            : myRowCount( rows )
            , myColumnCount( columns )
            , myData( rows * columns )
        {
        }
        //  ...
    };
    

    在这种情况下,const 明确表示 任何给定实例中的行和列都不会改变。 (在 另一方面,它阻止了默认赋值运算符 生成。这可能是也可能不是一件好事。)

    【讨论】:

      【解决方案4】:

      使用非静态 const 成员有一些限制。

      假设有 Employee 类。 首先,尽管编译器可以生成正确工作的复制构造函数,但它不能生成赋值运算符。如果程序创建两个 Employee 对象 e1 和 e2,则语句 e1 = e2 将导致编译器诊断。此分配无效,因为它隐式尝试更改 const 成员的值。 虽然你可以通过抛弃 const 来拥有赋值运算符,但这又不是一个好主意。

      另一个限制是很难为这个类提供一个有用的默认构造函数。如果要创建 Employee 对象数组,则默认构造函数是必不可少的。定义一个默认构造函数有点棘手;要记住的主要事情是 const 非静态数据成员在构造函数的初始化列表中被初始化 - 您必须初始化所有这些成员。默认构造函数必须将 dob 字段设置为某个值,并且该值不能随后更改。所以构造出来的数组实际上是没用的

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-11
        • 1970-01-01
        • 2012-08-07
        • 1970-01-01
        • 2012-10-20
        • 1970-01-01
        相关资源
        最近更新 更多