C++ Can';t从继承的类中为方法分配指针

C++ Can';t从继承的类中为方法分配指针,c++,C++,我有两门课: class IBaseA { public: virtual bool sayHello(std::string&) = 0; ~IBaseA(){} }; class BaseA: public IBaseA { public: virtual bool

我有两门课:

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(BaseA::)(std::string&){aka bool (BaseA::)(std::basic_string&)}'to'bool (IBaseA::)(std::string&{aka bool 初始化中的(IBaseA::)(std::basic_string&)}

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

但是如果我把作业改成

bool  (IBaseA::*ptr)(std::string&) = &IBaseA::sayHello;
这样我就可以毫无问题地使用这个指针了

BaseA A;
(A.*ptr)(str);
编辑:
谢谢你的回答,我在想,既然所有的地址都在vtable中,根据我从维基百科上了解到的,它们是同一个位置

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

始终考虑转换是否有效

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


指向成员的指针:
IBaseA
的所有成员也存在于
BaseA
中,因此您可以将指向
IBaseA
成员的指针转换为指向
BaseA
成员的指针。但是,并非
BaseA
的所有成员都存在于
IBaseA
中,因此不可能以相反的方式进行转换。

给定两个指向成员类型的指针
tc1::*P1
tc2::*P2
(其中T可能是函数类型),如果C2派生自C1,则只能将P1转换为P2。请注意,这与指向对象的指针相反,在对象中只能向上投射

原因是,如果您有一个指向基类成员的指针,则任何子类都保证也有该成员,因为它继承了该成员。反之则不适用


这是基本的类型转换规则。它不会因为您在那里使用的特定指针恰好是对基类中存在的虚拟函数的重写而改变。

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

bool  (IBaseA::*ptr)(std::string&) = &BaseA::sayHello;
本质上,这是这样的:我想要一个名为ptr的变量,它是指向IBaseA成员函数的指针,并且我想要它指向BaseA中的方法“sayHello”

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


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

虽然这似乎违反直觉,但您无法将指向派生类型成员的指针转换为指向基类成员的指针。正确的转换是另一种方式:可以将指向成员的指针转换为指向基的指针,将指向成员的指针转换为指向派生的指针

原因是,如果基类具有该成员,则派生类型保证具有该成员,但反过来则不是真的(即,指向派生类型的成员的指针可以引用已添加但不存在于基类中的成员)


您可能缺少的另一件事是,指向成员函数的指针是多态的,即,您可以存储
&IBase::sayHello
,如果应用它的成员的类型为
Base
最后一句话中的类型错误:不是
BaseA
的所有成员都存在于
IBaseA
bool  (IBaseA::*ptr)(std::string&) = &BaseA::sayHello;