2013-06-21 73 views
4

分配指针方法我有这样两类:无法从继承

class IBaseA 
{ 
public: 
    virtual bool sayHello(std::string&) = 0; 
    ~IBaseA(){} 
};                         

class BaseA: public IBaseA 
{ 
public: 
    virtual bool sayHello(std::string &str) 
    { 
    std::cout << "Hello " << str << std::endl; 
    return (true); 
    } 
    BaseA(){} 

}; 

你能解释我为什么我不能做这样的事情

bool (IBaseA::*ptr)(std::string&) = &BaseA::sayHello; 

error: cannot convert 'bool (BaseA::)(std::string&) {aka bool (BaseA::)(std::basic_string&)}' to 'bool (IBaseA::)(std::string&) {aka bool (IBaseA::)(std::basic_string&)}' in initialization

我不明白为什么我不能做这样的事情。

但是,如果我改变分配

bool (IBaseA::*ptr)(std::string&) = &IBaseA::sayHello; 

然后我可以使用这个指针没有任何问题

BaseA A; 
(A.*ptr)(str); 

编辑: 谢谢你的答案,我在想,因为所有的地址在vtable中,根据我从wikipedia中了解的内容,它们是相同的位置。

回答

5

指针到成员的转换与普通指针转换相反。您可以将指向派生类的指针转换为指向基类的指针,但反之亦然。您可以将基类的成员指针转换为派生类的指针成员,但反之亦然。

总是在想转换是否有效。

普通指针:BaseA的所有实例都是IBaseA的实例,因此转换是合法的。并非所有的IBaseA实例都是BaseA实例,因此您无法通过其他方式进行转换。

指针到成员:对IBaseA所有成员也出现在BaseA,所以你可以一个指针到成员的IBaseA转换成的BaseA一个指针到成员。然而,并非BaseA的所有成员都存在于IBaseA中,因此不可能通过其他方式进行转换。

+0

输入错误的最后一句:不是'BaseA'的所有成员都出现在'IBaseA' – yuan

+0

@yuan谢谢,修正。 – Angew

1

给出两个指针到成员类型T C1::*P1T C2::*P2(其中T可能是函数类型),如果C2从C1派生,则只能将P1转换为P2。请注意,这是指向对象的指针的逆转,您只能在此处进行上传。

的原因是,如果你有一个指向基类中的一员,任何子类保证拥有该成员太多,因为它继承了它。另一种方式不适用。

这是基本的类型转换规则。它不会因为那个特定的指针恰好是基类中存在的虚函数的覆盖而改变。

1

真正的答案可能是“因为语言规范说你不能”,但是,想想你正在尝试做的:

bool (IBaseA::*ptr)(std::string&) = &BaseA::sayHello; 

从本质上讲,这原文:我想一个叫做变量这是一个指向IBaseA成员函数的指针,我希望它指向BaseA中的sayHello方法。

是的,BaseA中的sayHello方法覆盖了IBaseA中的sayHello方法,但它们仍然是不同的方法。试想一下,如果您尝试使用指针来调用IBaseA类型的对象上的方法,那么其实不是实际上是BaseA--这在语法上是允许的,但您希望发生什么?

换句话说,通过获取指向派生类成员的指针并将其指定给一个声明为指向基类成员的变量,您将打破静态类型安全性。

1

虽然它看起来可能违反直觉,但您无法将派生类型的指针转​​换为指向成员的指针。正确的转换是另一种方式:您可以将指向成员的指针转换为指向成员的指针以派生。

原因是派生类型保证有该成员,如果基地有,但其他方式是不正确的(即指向派生类型的成员指向可以引用的成员是增加了而不存在于基地中)。

,你可能会丢失的另一件事是指针到成员函数是多态的,也就是说,你可以存储&IBase::sayHello,这将调用Base::sayHello如果要应用它的成员是Base类型。