一位同事问起这样的一些代码,其中最初有模板。
我删除了模板,但核心问题仍然存在:为什么编译好?
#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 ::执行这个指针是const。
但我可以通过成员函数指针调用非const成员函数。
成员函数指针是否是世界范围内记录在案的漏洞?
我们错过了什么(可能对他人来说很明显)?
答案 0 :(得分:10)
const
的{{1}}只会影响该类的execute()
指针。它使this
的类型为this
,而不仅仅是const T*
。这不是一个“深层”常量 - 它只意味着成员本身不能被改变,但他们指向或引用的任何东西仍然可以。您的T*
成员已无法更改,因为无法重新定位引用以指向其他任何内容。同样,您不是更改 object
成员,只是将其作为成员函数指针取消引用。所以这都是允许的,好的。
你制作你的CX const实例的事实并没有改变任何东西:再次,这指的是不允许被修改的直接成员,但是他们指向的任何东西仍然可以。您仍然可以在const对象上调用const成员函数,因此不会更改。
举例说明:
F
答案 1 :(得分:8)
在此上下文中,object
是对X
的引用,而不是对const X
的引用。 const
限定符将应用于成员(即引用,但引用不能是const
),而不是引用的对象。
如果您将类定义更改为不使用引用:
// ...
private:
X object;
// ...
你得到了你所期待的错误。
答案 2 :(得分:4)
object
的实例class X
不是常量。它仅由const对象引用。约束递归地应用于子对象,而不是引用的对象。
通过替代逻辑,const
方法将无法修改任何。这被称为“纯函数”,这是当前标准C ++中不存在的概念。
答案 3 :(得分:2)
您在foo
上呼叫object
,而不是this
。
由于object
被声明为X&
,因此在常量CX中,它实际上是X& const
(与const X&
不同),允许您调用非const方法就可以了。
答案 4 :(得分:0)
考虑它的一种有用方法可能是你的X对象根本不是CX的成员。