代码之家  ›  专栏  ›  技术社区  ›  dalle

对常量对象间接调用非常量函数

  •  3
  • dalle  · 技术社区  · 16 年前

    给定以下代码:

    class foo;
    
    foo* instance = NULL;
    
    class foo
    {
    public:
       explicit foo(int j)
        : i(j)
       {
          instance = this;
       }
    
       void inc()
       {
          ++i;
       }
    
    private:
       int i;
    };
    

    const foo f(0);
    
    int main()
    {
       instance->inc();
    }
    

    我这样问是因为我使用的是一个类注册表,因为我没有直接修改 f 很高兴能来 const ,但后来 F

    const_cast 它可能会导致未定义的行为,例如:

    int main()
    {
        const int i = 42;
        const_cast<int&>(i) = 0; // UB
    }
    
    7 回复  |  直到 16 年前
        1
  •  4
  •   avakar    16 年前

    是,根据7.1.5.1/4,这是未定义的行为:

    除了任何声明为可变(7.1.1)的类成员都可以修改外,任何在常量对象的生存期(3.8)内修改常量对象的尝试都会导致未定义的行为。

    请注意,当构造函数调用完成时(3.8/1),对象的生存期开始。

        2
  •  2
  •   Andreas Bonini    16 年前

    这可能是一个罕见的情况下,不太了解 mutable

    mutable int i;

    i 逻辑上


    例如:

    class SomeClass
    {
    // ....
        void DoSomething() { mMutex.lock(); ...; }
        mutable Mutex mMutex;
    }
    

    DoSomething() 对象在逻辑上不会更改,但mMutex必须更改才能锁定它。所以这是有道理的 易变的 const (假设每次操作都锁定muetx)。

        3
  •  2
  •   Jerry Coffin    16 年前

    如果定义对象的常量实例,然后丢弃常量并修改对象的内容,则会得到未定义的行为。

    从表面上看,您想要的恰恰相反:创建对象的非常量实例,然后将指向该对象的常量指针返回(大多数)客户端,而“所有者”保留指向该对象的非常量指针,以便它可以根据需要修改成员。

    您通常会通过定义带有私有ctor的类来管理这种情况,因此大多数客户机无法创建这种类型的对象。然后,该类将把所有者类声明为友元,这样它就可以使用私有ctor和/或静态成员函数来创建对象的实例(通常只创建一个实例)。然后,owner类将指针(或引用)传递给const对象供客户端使用。您既不需要可变成员,也不需要丢弃常量,因为拥有修改对象“权利”的所有者始终拥有指向该对象的非常量指针(或引用)。它的客户端只接收常量指针/引用,防止修改。

        4
  •  1
  •   AnT stands with Russia    16 年前

    const_cast 或者使用构造函数的技巧,如您的示例中所示。

    但是,仅当您正在调用的成员函数没有尝试实际执行时,才会定义该行为 修改 对象(即修改常量对象的不可变成员)。一旦它尝试执行修改,行为将变得未定义。在你的情况下,方法 inc

    仅仅调用这个方法也是完全合法的。

        5
  •  0
  •   Joe Mabel    16 年前

    用这些任意的名字很难说出目的。如果 i 只是作为一个使用计数器,并且它实际上并不被视为数据的一部分,那么将其声明为 mutable int i; const -当 我 是修改过的。另一方面,如果 我

    然而,与此不同的是,你的例子对于你似乎提出的问题来说有点混乱。 foo* instance = NULL; NULL 作为数字零和初始化 instance 常数 ; 然后分别初始化 f 常数 ,但决不引用它。

        6
  •  0
  •   Chip Uni    16 年前

    explicit foo(int j) 用这个词 int .

    但是,有两个指针指向同一个值是非常好的,一个指针 const 另一个不是。

        7
  •  0
  •   Ashish    16 年前

    你为什么不利用const cast呢?

    如果对象的状态不是常数,有什么理由使其成为常数吗?

    explicit foo(int j = 0)    : i(j)   
    
    {    instance = this;   }
    
    推荐文章