C++、类、常量和奇怪的语法

2022-01-24 00:00:00 class reference constants c++

我今天在重读 c++ 入门(第 4 版)――关于成员函数和 const 引用等的部分,我想出了这个奇怪的小程序:

I was re-reading c++ primer(4th ed.) today - the section on member functions and const references etc, and I came up with this wierd little program:

using std::cout;
using std::endl;

class ConstCheater
{
public:
    ConstCheater(int avalue) : ccp(this), value(avalue) {}
    ConstCheater& getccp() const {return *ccp;}
    int value;
private:
    ConstCheater* ccp;
};

int main()
{
    const ConstCheater cc(7); //Initialize the value to 7
    cout << cc.value << endl;
    cc.getccp().value = 4;    //Now setting it to 4, even though it's const!
    cout << cc.value << endl;
    cc.value = 4;             //This is illegal
    return 0;
}

我的问题是 - 为什么 c++ 允许这样的语法?为什么我可以在声明为 const 的类中编辑普通数据成员?const的要点不就是让你不能修改值吗?

My question is - why does c++ allow syntax such as this? Why can I edit normal data members in a class when it's declared const? Isn't the POINT of const to make it so that you can't modify values?

推荐答案

我会说你标记为正确的 Tony 的答案是不正确的,Michael Burr 的答案是正确的.

I'd say the answer by Tony that you marked as correct is incorrect, and the answer by Michael Burr is correct.

为了更清楚地表达他所说的(至少对我而言):

To put what he said more clearly (for me at least):

有两个可能产生误解的地方:

There are two potential places for misunderstanding:

  1. 隐式 const 的工作方式
  2. this 在构造 const 对象期间的解释方式
  1. The way implicit const works
  2. The way that this is interpreted during construction of a const object

<小时>

1.隐式常量

Implicit const(ConstCheater 内部的 constification 当它被制成 const 时)不会将 cc 变成 pointer-to-const 而是一个const-pointer,也就是说当你这样做的时候:


1. Implicit Const

Implicit const (the constification internal to ConstCheater when it is made const) doesn't turn cc into a pointer-to-const but rather a const-pointer, that is to say when you do this:

  const ConstCheater cc(7); 

内部来自:

  ConstCheater * ccp;

...到...

  ConstCheater * const ccp;

...而不是...

  const ConstCheater * ccp;    

这可能是意料之中的.

奇怪的是,自从 this 以来,允许将 this 传递给构造函数中的 cpp 的初始化程序,人们会认为,应该被视为 pointer-to-const,因此不是传递给 const-pointer 的有效值.

The stranger thing is though is that this is allowed to be passed to cpp's initializer in the constructor since this, one would think, should be treated as a pointer-to-const, and thus not a valid value to pass to a const-pointer.

也就是说人们可能期望:

That is to say one might expect:

 ...: ccp(this) ... // expected to fail but doesnt

失败,因为从概念上讲,您可能期望这(在某种程度上)等同于:

to fail because conceptually you might expect that this was (somewhat) equivalent to:

 const ConstCheater         cc(7);
 const ConstCheater * const this = &cc; // const-pointer-to-const

因此你会认为:

 ConstCheater * const ccp = this; //expected error!

会失败!但它不是因为显然在构造过程中,显然 this 被特殊对待,就好像它是:

would fail! But it doesn't because apparently during construction apparently this is treated specially as if it was:

 const ConstCheater * this = &cc; 

因此对象在构造过程中实际上不是 const.

and thus the object is effectively not const during construction.

我不确定我是否完全理解其中的原因,但 Michael Burr 指出,提供预期行为似乎存在逻辑和技术障碍,因此该标准似乎排除了当前有些奇怪的行为.

I'm not sure I understand completely the reasoning, but Michael Burr points out there appears to be a logical and technical barrier to providing the expected behavior so the standard seems to carve out the current somewhat odd behavior.

我最近问了一个相关问题:为什么 C++ 不有一个 const 构造函数? 但到目前为止还没有真正完全理解为什么它会站不住脚的原因,尽管我认为这会给 C++ 开发人员带来负担,必须为他们的任何类定义一个笨拙的 const 构造函数'想创建 const 对象.

I recently asked a related question which was: Why does C++ not have a const constructor? but thus far haven't really understood completely the reasoning why it would be untenable, though I suppose it would place a burden on C++ developers to have to define an awkward const constructor for any class they'd like to create const object of.

相关文章