【问题标题】:Why can I call a non-const member function pointer from a const method?为什么我可以从 const 方法调用非常量成员函数指针?
【发布时间】:2010-03-26 13:26:01
【问题描述】:

一位同事询问了一些类似这样的代码,其中最初包含模板。

我已经删除了模板,但核心问题仍然存在:为什么编译正常?

#include <iostream>

class X
{
public:
     void foo() { std::cout << "Here\n"; }
};

typedef void (X::*XFUNC)() ;

class CX
{
public:
    explicit CX(X& t, XFUNC xF) : object(t), F(xF) {}      
    void execute() const { (object.*F)(); }
private:
    X& object;
    XFUNC F;
}; 

int main(int argc, char* argv[])
{   
    X x; 
    const CX cx(x,&X::foo);
    cx.execute();
    return 0;
}

鉴于CX是一个const对象,它的成员函数execute是const,所以CX::execute里面的this指针是const。

但我可以通过成员函数指针调用非常量成员函数。

成员函数指针是世界常量中的一个记录漏洞吗?

我们遗漏了什么(可能对其他人来说很明显)问题?

【问题讨论】:

    标签: c++


    【解决方案1】:

    execute()constness 只影响类的this 指针。它使this 的类型变为const T* 而不仅仅是T*。这不是一个“深”的常量——它只意味着成员本身不能被改变,但他们指向或引用的任何东西仍然可以。您的object 成员已经无法更改,因为无法重新定位引用以指向其他任何内容。同样,您没有更改 F 成员,只是将其取消引用为成员函数指针。所以这一切都是允许的,OK。

    您将 CX 实例设为 const 的事实并没有改变任何东西:同样,这指的是不允许修改直接成员,但它们指向的任何东西仍然可以。您仍然可以在 const 对象上调用 const 成员函数,因此无需更改。

    举例说明:

    class MyClass
    {
    public:
        /* ... */
    
        int* p;
    
        void f() const
        {
            // member p becomes: int* const p
            *p = 5;   // not changing p itself, only the thing it points to - allowed
            p = NULL; // changing content of p in const function - not allowed
        }
    };
    

    【讨论】:

    • 重要的是要注意,您基本上可以将T&amp; 视为T* const。无论如何,我同意const 的浅层传播很奇怪,但我们也默认有浅层副本......
    【解决方案2】:

    在这种情况下,objectX的引用,而不是对 const X的引用const 限定符将应用于成员(即引用,但引用不能是 const),而不是被引用的对象。

    如果您将类定义更改为不使用引用:

    // ...
    private:
        X object;
    // ...
    

    你得到了你所期望的错误。

    【讨论】:

    • 不过,使用const-methods 应该只能在成员对象上调用const-methods,不是吗?
    • 成员是引用,不是被引用的对象。
    【解决方案3】:

    class X 的实例 object 不是 const。它仅被一个 const 对象引用。常量递归地应用于子对象,而不是引用的对象。

    按照替代逻辑,const 方法将无法修改任何内容。这就是所谓的“纯函数”,这是当前标准 C++ 中不存在的概念。

    【讨论】:

      【解决方案4】:

      您在object 上呼叫foo,而不是在this 上。

      由于object 被声明为X&amp;,在常量CX 中,它实际上是一个X&amp; const(与const X&amp; 不同),允许您在其上调用非const 方法。

      【讨论】:

      • 我觉得你应该提到“X& const”在语言中是没有意义的,因为没有“引用重新绑定”这样的东西。
      【解决方案5】:

      一种有用的思考方式可能是您的 X 对象根本不是 CX 的成员。

      【讨论】:

      • 你可以这样想,但不管是不是。该类可以有一个 X 实例 (object) 作为成员,也可以有一个引用成员来引用它。然后你会发现你不能做(object.*F)();,但仍然可以做(reference.*F)();,即使它引用了 CX 成员的完全相同的东西。
      猜你喜欢
      • 2016-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-12
      • 1970-01-01
      • 1970-01-01
      • 2020-02-12
      • 1970-01-01
      相关资源
      最近更新 更多