【问题标题】:Modifying self within const method via non const pointer to self在 const 方法中通过指向 self 的非 const 指针修改 self
【发布时间】:2014-02-26 21:31:33
【问题描述】:

在以下示例中,const 对象可以通过const 方法修改自己,因为在该方法中它通过non-const 指针访问自己。 (same program on ideone)

#include <iostream>

struct Object;

Object * g_pObject;

struct Object
{
    Object():m_a(0){}

    void ModifySelfViaConstMethod() const
    {
        g_pObject->m_a = 37;
    }

    int m_a;
};

int main()
{
    Object o;
    g_pObject = &o;

    const Object & co = o;
    std::cout << co.m_a << "\n";
    co.ModifySelfViaConstMethod();
    std::cout << co.m_a << "\n";

    return 0;
}

我不太擅长阅读c++标准,所以在这里问:

标准对此有何评论?

a)const 方法并不能保证在您执行此类操作时您的对象保持不变

b) 是否定义明确且必须编译

c) 其他?

【问题讨论】:

  • 非常糟糕的主意。变异成员函数通常不声明const

标签: c++ constants


【解决方案1】:

当您声明 const 函数时,它是“为您好”。

换句话说,您声明它const,因为根据您的初始设计,它不应该更改在运行时调用它的任何对象。

如果在稍后执行此函数的某个时间点您最终更改了对象,编译器会“对您大喊大叫”,告诉您这是错误的。

当然,编译器将能够识别这种尝试,只有在应用于this时。

在给定的示例中,编译器无法识别问题,因为它需要在 thisg_pObject 之间进行比较,并且这种比较只能在运行时进行。

【讨论】:

    【解决方案2】:

    当一个方法被声明为const 时,编译器确保this 指针指向的实例不被修改。如果尝试修改this 实例,编译器会失败。但是,编译器无法知道g_pObjectthis 实际上指向同一个实例。这需要运行时比较,并且没有编译器会浪费时间对 const 方法中使用的每个指针执行运行时比较,因为它们可能匹配 @ 987654327@ 指针。因此,如果您要通过外部指针修改Object,则必须自己进行检查,例如:

    void ModifySelfViaConstMethod() const
    {
        if (g_pObject != this)
            g_pObject->m_a = 37;
    }
    

    【讨论】:

      【解决方案3】:

      标准对此有何评论?

      它说(释义)this 的类型为const Object *,因此您不能直接修改成员或通过this 调用非常量成员函数。它没有说明您可以对函数可能访问的任何全局变量做什么;它只控制对调用该函数的对象的直接访问。

      const 方法并不能保证在您执行此类操作时您的对象保持不变

      不,它没有。它声明了函数不会修改对象的意图,并提供了一些防止意外破坏该意图的保护。它不会阻止适当的精神错乱的程序员使用const_cast,或者(如这里)通过全局变量不受控制的耦合来破坏承诺。

      它定义得很好,它必须编译

      是的。 o 本身并不是常量,因此没有什么可以阻止您使用非常量指针或引用它。成员函数上的const 仅限制通过this 访问对象,而不限制通过其他指针访问任意对象。

      【讨论】:

      • 这就是我要找的答案,谢谢!
      【解决方案4】:

      C++ 中的恒定性是一种安全工具,而不是安全性。

      遵守恒常性的代码很可能会按预期工作,编译器会提醒所有无意中放弃恒常性的尝试。

      在“我知道自己在做什么”的情况下,可以找到各种工具,从 const_cast 运算符和 mutable 关键字到平庸的 C 风格转换。

      【讨论】:

        猜你喜欢
        • 2011-01-31
        • 2020-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多