请澄清 const 限定符传播
Posted
技术标签:
【中文标题】请澄清 const 限定符传播【英文标题】:Please clarify const qualifier propagation 【发布时间】:2016-05-18 09:35:12 【问题描述】:假设我们有以下一段代码:
class Base
public:
int a = 5;
;
class Derived : public Base
public:
Base *parent_ = new Base;
Base* parent() const return parent_;
;
void f(const Derived *derived)
Base *p = derived->parent();
p->a = 10; // <- is this correct?
我个人认为这是一个问题:
在函数
f
中,我们获取一个指向const
类Derived
对象的指针。这使得它的每个成员也是const
,因此parent_
变为const Base *
。如果它是 const,我们不应该有能力修改指针指向的对象。
我哪里错了?
【问题讨论】:
parent_
的类型是 Base * const
,而不是 const Base *
。
@sashoalm yes.
顺便说一句,问题并不是真正特定于继承。恕我直言,最好编辑和删除任何继承的东西
好吧,您的代码中有继承,但问题不是由此引起的。答案甚至没有提到继承。恕我直言,更好的标题是“返回指针时澄清 const 限定符”
@VictorPolevoy : tobi303 指的是 Derived
在您的代码示例中继承自 Base
- 这对您的问题没有影响,实际上可能会导致一些混淆 Base
的使用作为基类和成员。
【参考方案1】:
这使得它的每个成员也是 const 从而
parent_
变为const Base *
。
不,指针将变为 const 本身,而不是它指向的对象。所以parent_
变成Base * const
,而不是const Base *
,你的代码是有效的。
【讨论】:
【参考方案2】:Base* parent() const return parent_;
不幸的是,这是 C++ 的问题。方法是const
,但它返回一个非常量指针,这将允许以下操作成功:
p->a = 10; // <- is this correct?
程序员有责任不从函数返回非常量指针或引用(方法是否为 const)。
【讨论】:
根据@songyuanyao 的回答,这不是问题,因为我们更改了保留为non-const
的对象,因为唯一由const propagation
变为const
的是指针本身。跨度>
@VictorPolevoy 我会说这是个问题。你没有打破语言,但你打破了逻辑的不变性。【参考方案3】:
正如 tobi303 在下面指出的,这个答案是错误的。为了下面的讨论,将其保留在这里。
我可能是错的,但是这一行:
Base* parent() const return parent_;
没有提到任何关于返回 const 对象的内容。相当于
Base* parent() const return this->parent_;
其中this
是const Derived*
,但parent_
仍然是Base*
。
【讨论】:
const
对象的成员也是const
,否则整个const
故事对于公共成员来说毫无用处
@tobi303 你好像不明白const T *
和T * const
的区别
this
是 const Derived* const
,parent_
是 Base* const
。
@M.M 我明白其中的区别。但正如宋元耀所指出的,如果this
是const
,那么它的成员parent_
也是const
。由于该成员是一个指针,因此作为const
对象的成员,它成为const
指针(指向一个非常量对象)。实际上,我无意将此答案称为“错误”....
@tobi303,我真的很感谢你纠正了我。也许应该将当前讨论的简明版本编辑为已接受的答案。【参考方案4】:
const 方法仅防止该方法修改类的任何非可变数据成员。
如果你不想让a
的修改,又不想更新类,你需要写:
const Base *p = derived->parent();
但是,我建议您不要将类中的非常量数据成员作为 ref 或指针返回,因为这破坏了 C++ 的数据封装概念。当然,公众号a
也是如此。
【讨论】:
以上是关于请澄清 const 限定符传播的主要内容,如果未能解决你的问题,请参考以下文章