2010-03-26 141 views
5

一位同事询问了一些原来有模板的代码。为什么我可以从const方法调用非const成员函数指针?

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

#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对象,它的成员函数执行是常量,因此内部CX ::执行指针是常量。

但我能够通过成员函数指针调用非const成员函数。

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

我们错过了什么(大概很明显是他人)问题?

回答

7

在此上下文中object参照X,而不是一个参照一个const Xconst限定符将应用于成员(即引用,但引用不能为const),而不适用于引用的对象。

如果你改变你的类定义不使用参考:

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

你得到你所期待的错误。

+0

尽管如此,用'const'方法只能在成员对象上调用'const'方法,是不是正确? – 2010-03-26 13:34:30

+3

成员是引用,而不是引用的对象。 – 2010-03-26 13:37:18

7

​​的const只影响类的指针this。它使得类型this a const T*而不是仅仅T*。尽管这不是一个'深'的常量 - 它只意味着成员本身不能被改变,但是他们指向或引用的任何东西仍然可以。您的object成员已经无法更改,因为引用无法重新指向其他任何内容。同样,你不是更改F成员,只是将其解除引用作为成员函数指针。所以这是全部允许的,并且确定。

事实上,你让你的实例CX常量不会改变任何东西:再次,这是指直接成员不被允许修改,但他们指出的任何东西仍然可以。你仍然可以在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 
    } 
}; 
+1

重要的是要注意,你基本上可以把'T&'当作'T * const'。无论如何,我同意'const'的浅度传播很奇怪,但是我们也有默认的浅拷贝... – 2010-03-26 13:54:45

3

实例的class Xobject不是常量。它只是由一个const对象引用。 Constra ness递归应用于子对象,而不是引用对象。

通过替代逻辑,const方法将不能修改任何东西。这被称为“纯函数”,这是目前标准C++中不存在的一个概念。

1

您正在致电fooobject而不是this

由于object被声明为X&,在恒定的CX,它实际上是一个X& const(这是不一样的const X&)允许你调用它的非const的方法。

+0

我觉得你应该提到“X&const”在语言中是非感性的,因为有没有'引用重新绑定'这样的东西。 – 2013-07-24 09:51:09

0

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

+0

你可以这样想,但不管它是否是。该类可以有一个X实例('object')作为成员,并且还可以引用该实例。然后你会发现你不能做'(object。* F)();',但是仍然可以做'(reference。* F)();',尽管它引用了完全相同的事物,即** ** CX的成员。 – UncleBens 2010-03-26 16:29:34

相关问题