我知道这已经被问了很多,但我能找到的唯一答案就是当使用(int *)或类似的东西实际输出const。时。当没有涉及强制转换时,为什么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();
}
上面的代码产生以下输出(在gcc 4.5.2和vc100中测试):
foo::doit() const calling mybar1->doit() bar::doit() non-const <-- Why ? calling mybar2.doit() bar::doit() const
答案 0 :(得分:15)
当一个foo实例是const时,它的数据成员也是const,但这对指针的适用方式与你最初想的不同:
struct A {
int *p;
};
A const obj;
obj.p的类型是int * const,而不是int const *;也就是说,一个指向int的常量指针,而不是指向常量int的指针。
另一种看待它的方法,让我们从一个函数开始:
template<class T>
T const& const_(T const &x) {
return x;
}
现在假设我们有一个A实例,我们将它设为const。您可以想象在每个数据成员上应用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 *".
变量be_wary_of_where_you_place_const显示“添加const”不与将“const”添加到类型的文字文本相同。
答案 1 :(得分:1)
在这种情况下,我将回答我自己的问题。 Fred Nurk的答案是正确的,但并没有真正解释“为什么”。 mybar1
和*mybar1
不同。第一个引用实际指针,后者引用对象。指针是const(由foo上的常量强制要求;你不能做mybar1 = 0
),而不是指向对象,因为这需要我声明它const bar* mybar1
。当foo对象为const时,声明bar* mybar1
等同于bar* const mybar1
(即指针是const,不指向对象)。
答案 2 :(得分:0)
默认情况下,C ++给出了一个所谓的按位常量 - 这意味着它确保没有任何单个对象位被更改,所以它只是检查指针的地址。
你可以在精彩的书中阅读更多相关信息&#34; Effective c ++&#34;作者:S. Meyers