Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't assign a pointer to method from an inherited class

Tags:

c++

I have this two class:

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(){}

};

Can you explain me why I'm not able to do something like that

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

I don't understand why I can't do something like this.

But if I change the assignment to

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

then I can use this pointer without any problems

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

edit: Thanks for the answers, I was thinking that since all the addresses are in the vtable, they are the same location according of what I understood from wikipedia.

like image 994
Alexis Avatar asked Feb 17 '23 04:02

Alexis


2 Answers

Pointer-to-member conversions work opposite to normal pointer conversion. You can convert a pointer to derived class into a pointer to base class, but not vice versa. You can convert a pointer-to-member of base class to pointer-to-member of derived class, but not vice versa.

Always think whether the conversion is valid.

Plain pointers: All instances of BaseA are instances of IBaseA, so that conversion is legal. Not all IBaseA instances are BaseA instances, so you can't convert the other way.

Pointers-to-member: All members of IBaseA are also present in BaseA, so you can convert a pointer-to-member of IBaseA into a pointer-to-member of BaseA. Not all members of BaseA are present in IBaseA, however, so conversion the other way round is not possible.

like image 162
Angew is no longer proud of SO Avatar answered Mar 06 '23 08:03

Angew is no longer proud of SO


Given two pointer-to-member types T C1::*P1 and T C2::*P2 (where T might be a function type), you can only convert P1 to P2 if C2 derives from C1. Note that this is the inverse of pointers to objects, where you can only upcast.

The reason is that if you have a pointer to a member of the base class, any subclass is guaranteed to have that member too, since it inherited it. The other way round does not apply.

This is the basic type conversion rule. It doesn't change just because that particular pointer you are taking there happens to be an override of a virtual function that exists in the base class.

like image 34
Sebastian Redl Avatar answered Mar 06 '23 06:03

Sebastian Redl