我很惊讶地发现“const”中的这个“漏洞”:
#include <stdio.h>
class A
{
int r ;
public:
A():r(0){}
void nonconst()
{
puts( "I am in ur nonconst method" ) ;
r++;
}
} ;
class B
{
A a ;
A* aPtr ;
public:
B(){ aPtr = new A() ; }
void go() const
{
//a.nonconst() ; // illegal
aPtr->nonconst() ; //legal
}
} ;
int main()
{
B b ;
b.go() ;
}
所以基本上从const
方法B::go()
开始,如果类型为{{1}的对象,则可以调用非const 成员函数(恰当地命名为nonconst()
)由指针引用。
为什么?看起来像是一个问题(它在我的代码中,我找到了它。)
答案 0 :(得分:11)
何时类型B
的对象是const,那么它的所有成员都是const,这意味着它的两个成员在B::go()
期间有效
A const a;
A * const aPtr;
第一个是A
类型的常量对象,您只能在其上调用const成员函数。然而,第二个是指向非常数A
的常量指针。您无法在函数aPtr = <anything>
内合法地说B::go()
,因为这会修改aPtr
,这是常量。
指向常量A
的指针将被声明为A const* aPtr
或const A* aPtr
,这会使调用非常量A::nonconst()
非法。
答案 1 :(得分:6)
对象的“常量”不通过指针扩展到其他对象。在您的示例中,const
部分是整个对象a
,或指针 aPtr
。由于aPtr
是A *
而不是const A *
,因此您可以调用非const方法。
如果你改变了
A* aPtr ;
到
const A* aPtr ;
然后您将无法拨打aPtr->nonconst()
。
答案 2 :(得分:0)
const
我很惊讶地发现“const”中的这个“漏洞”:
没有。
const
将统一应用于所有班级成员:在班级const
的{{1}}成员函数中,C
的类型为this
},因此对于声明为const C *
类型的成员C::mem
:
T
class C {
// ...
T mem;
};
的类型为this->mem
。
请使用type来识别所有成员的声明类型const T
和相应的const限定类型。
看起来像是一个问题(它出现在我的代码中,我找到了它。)
仅仅因为系统应用规则没有达到您的预期并不意味着规则存在问题,这意味着您的期望存在问题。
如果T
属于不同类型,您应该写下您的期望,以确保您预期会出现非统一的申请。
编程时,你必须在逻辑上进行推理。你应该推断出事物,在没有合理逻辑的情况下不要指望它们。
const
为什么?
您的课程被称为const
和A
,很难理解什么是逻辑状态,什么不是。 ;)你问一个“道德”问题(不只是关于合法/非法C ++程序的问题),而你的代码片段没有“道德”价值。如果您实际发布相关代码,我们可能会做出一些“道德”判断。
您应该声明B
不会更改其应用对象的“逻辑状态”的函数。
这意味着你必须定义类实例的“逻辑状态”:它是一个抽象的概念,只有你可以定义它,因为它是一个高级概念。 “逻辑状态”与您的课程应解决的问题有关。
然后你可以看出哪些变量对逻辑状态有贡献:const
是否有助于*(b.aPtr)
的逻辑状态?
你知道复制构造函数吗?
关于复制赋值运算符?
关于析构函数?