我读了发布的问题 Why does C++ not have a const constructor?
我仍然感到困惑,为什么该程序可以编译。我试图就这个问题提出我的看法,我不知道为什么它被删除了。所以我不得不再问这个问题。
这是程序
class Cheater
{
public:
Cheater(int avalue) :
value(avalue),
cheaterPtr(this) //conceptually odd legality in const Cheater ctor
{}
Cheater& getCheaterPtr() const {return *cheaterPtr;}
int value;
private:
Cheater * cheaterPtr;
};
int main()
{
const Cheater cheater(7); //Initialize the value to 7
// cheater.value = 4; //good, illegal
cheater.getCheaterPtr().value = 4; //oops, legal
return 0;
}
我的困惑是:
const Cheater cheater(7)
在构造函数
Cheater(int avalue) :
value(avalue),
cheaterPtr(this) //conceptually odd legality in const Cheater ctor
{}
'this'指针用于初始化cheaterPtr
。
我认为这不应该是正确的。 cheater
是一个const对象,它的指针应该是这样的:const Cheater* const this;
这意味着它自己的指针和指针所指向的对象都应该是const,我们既不能改变指针的值,也不能改变指针的值。修改指针指向的对象。
但是对象cheater
的{{1}}成员类似于cheaterPtr
。这意味着指针是const,但它指向的对象可能是非对象的。
我们知道,不允许指向const到指针转换为非指针转换:
Cheater* const cheaterPtr
如何在初始化列表中允许从指针到const到指针到非对象的转换?真的发生了什么?
以下是关于我试图提供给原始帖子的构造函数中“constness”的描述:
“与其他成员函数不同,构造函数可能不会被声明为const。当我们创建类类型的const对象时,在构造函数完成对象的初始化之后,对象才会假定它的'constness'。因此,构造函数可以在构造期间写入const对象。“
- C ++入门(第5版)P262 7.1.4构造函数
答案 0 :(得分:3)
如果构造函数是const
,则它们无法构造它们的对象 - 它们无法写入其数据!
您引用的代码为“合法:”
cheater.getCheaterPtr().value = 4; //oops, legal
实际上并不合法。在编译时,它的行为是未定义的,因为它通过非const左值修改const
对象。它与此完全相同:
const int value = 0;
const int * p = &value;
*const_cast<int*>(p) = 4;
这也会编译,但它仍然是非法的(有UB)。
答案 1 :(得分:1)
您的假设不正确。一次取一个,首先是代码注释。
class Cheater
{
public:
Cheater(int avalue) :
value(avalue),
cheaterPtr(this) // NOTE: perfectly legal, as *this is non-const
// in the construction context.
{}
// NOTE: method is viable as const. it makes no modifications
// to any members, invokes no non-const member functions, and
// makes no attempt to pass *this as a non-const parameter. the
// code neither knows, nor cares whether `cheaterPtr`points to
// *this or not.
Cheater& getCheaterPtr() const {return *cheaterPtr;}
int value;
private:
Cheater * cheaterPtr; // NOTE: member pointer is non-const.
};
int main()
{
// NOTE: perfectly ok. we're creating a const Cheater object
// which means we cannot fire non-const members or pass it
// by reference or address as a non-const parameter to anything.
const Cheater cheater(7);
// NOTE: completely lega. Invoking a const-method on a const
// object. That it returns a non-const reference is irrelevant
// to the const-ness of the object and member function.
cheater.getCheaterPtr().value = 4;
return 0;
}
你说:
施工后我认为这不应该是正确的。 cheater是一个const对象,其指针应该类似于:
const Cheater* const this
cheater
const
。在构造期间它必须是非const 。此外,构造函数不会(也不能)知道调用者已指示对象将为const
。所有它知道的是它构建一个对象的时间,这就是它的作用。此外,构建后{em> &cheater
为const Cheater *
。实际指针变量本身const
在这种情况下根本不适用。
然后......
...对象骗子的cheaterPtr成员类似于
Cheater* const cheaterPtr;
这实际上是一种非常准确的描述方式。由于cheater
是const
,其成员也是如此,这意味着cheaterPtr
成员是const
; 不 指向的内容。您无法更改指针值,但因为它不是指向const对象的指针,您可以自由地使用该指针来修改它指向的内容,在这种情况下恰好是this
。
如果您希望两者指针及其指向对象为const,您应该在成员列表中将其声明为const Cheater *cheaterPtr;
。 (并且这样做,顺便说一句,只通过getCheaterPointer()
的可变行为无效。它也必须返回const Cheater*
,这当然意味着分配失败。
简而言之,此代码完全有效。您想要看到的内容(调用者 const-ness的构建意识)不是该语言的一部分,事实上,如果您希望构造函数具有...的自由度,那么事实并非如此。 ,构造。