简体   繁体   English

为什么const限定符不能处理const对象上的指针成员?

[英]Why isn't the const qualifier working on pointer members on const objects?

I know this has been asked a lot, but the only answers I could find was when the const-ness was actually casted away using (int*) or similar. 我知道这已被问过很多,但我能找到的唯一答案就是当const-ness实际上是使用(int *)或类似的方法进行的。 Why isn't the const qualifier working on pointer type member variables on const objects when no cast is involved? 当没有涉及强制转换时,为什么const限定符不在const对象上处理指针类型成员变量?

#include <iostream>

class bar {
public:
    void doit()       { std::cout << "    bar::doit() non-const\n"; }
    void doit() const { std::cout << "    bar::doit() const\n"; }
};

class foo {
    bar* mybar1;
    bar mybar2;
public:
    foo() : mybar1(new bar) {}
    void doit() const {
        std::cout << "foo::doit() const\n";
        std::cout << "  calling mybar1->doit()\n";
        mybar1->doit();  // This calls bar::doit() instead of bar::doit() const
        std::cout << "  calling mybar2.doit()\n";
        mybar2.doit(); // This calls bar::doit() const correctly
    }
    // ... (proper copying elided for brevity)
};

int main(void)
{
    const foo foobar;  // NOTE: foobar is const
    foobar.doit();
}

The code above yields the following output (tested in gcc 4.5.2 and vc100): 上面的代码产生以下输出(在gcc 4.5.2和vc100中测试):

foo::doit() const
  calling mybar1->doit()
    bar::doit() non-const         <-- Why ?
  calling mybar2.doit()
    bar::doit() const

When a foo instance is const, its data members are const too, but this applies differently for pointers than you might at first think: 当foo实例是const时,它的数据成员也是const,但这对于指针的适用方式与您最初想的不同:

struct A {
  int *p;
};

A const obj;

The type of obj.p is int * const, not int const *; obj.p的类型是int * const,而不是int const *; that is, a constant pointer to int, not a pointer to constant int. 也就是说,一个指向int的常量指针,而不是指向常量int的指针。

For another way to look at it, let's start with a function: 另一种看待它的方法,让我们从一个函数开始:

template<class T>
T const& const_(T const &x) {
  return x;
}

Now imagine we have an A instance, and we make it const. 现在假设我们有一个A实例,我们将它设为const。 You can imagine that as applying const_ on each data member. 您可以想象在每个数据成员上应用const_。

A nc;
// nc.p has type int*.
typedef int *T;  // T is the type of nc.p.

T const &p_when_nc_is_const = const_(nc.p);
// "T const" is "int * const".

const T &be_wary_of_where_you_place_const = const_(nc.p);
// "const T" is "int * const".
// "const T" is *not* "const int *".

The variable be_wary_of_where_you_place_const shows that "adding const" is not the same as prepending "const" to the literal text of a type. 可变be_wary_of_where_you_place_const显示,“添加常量”是一样的预谋“常量”的类型的文字的文本。

I am going to answer my own question in this case. 在这种情况下,我将回答我自己的问题。 Fred Nurk's answer is correct but does not really explain the "why". Fred Nurk的答案是正确的,但并没有真正解释“为什么”。 mybar1 and *mybar1 are different. mybar1*mybar1不同。 The first refer to the actual pointer and the latter the object. 第一个引用实际指针,后者引用对象。 The pointer is const (as mandated by the const-ness on foo; you can't do mybar1 = 0 ), but not the pointed to object, as that would require me to declare it const bar* mybar1 . 指针是const(由foo上的常量强制要求;你不能做mybar1 = 0 ),而不是指向对象,因为这需要我声明它为const bar* mybar1 The declaration bar* mybar1 is equivalent to bar* const mybar1 when the foo object is const (ie pointer is const, not pointed to object). 当foo对象为const时,声明bar* mybar1等效于bar* const mybar1 (即指针是const,不指向对象)。

C++ by default gives a so called bitwise constness - meaning it ensures that no single bit of object has been changed, so it just checks the address of the pointer. 默认情况下,C ++给出了一个所谓的按位常量 - 这意味着它确保没有任何单个对象位被更改,所以它只是检查指针的地址。

You can read more about it in great book "Effective c++" by S. Meyers 您可以在S. Meyers的精彩书籍“Effective c ++”中阅读更多相关内容

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM