How to Call Derived Class Method from Base Class Pointer

How to call derived class method from base class pointer?

You need to make DoSomething() a virtual function in both classes to get the polymorphic behavior you're after:

virtual void DoSomething(int i) { ...

You don't need to implement virtual functions in every sub class, as shown in the following example:

#include <iostream>

class A {
public:
virtual void print_me(void) {
std::cout << "I'm A" << std::endl;
}

virtual ~A() {}
};

class B : public A {
public:
virtual void print_me(void) {
std::cout << "I'm B" << std::endl;
}
};

class C : public A {
};

int main() {

A a;
B b;
C c;

A* p = &a;
p->print_me();

p = &b;
p->print_me();

p = &c;
p->print_me();

return 0;
}

Output:

I'm A

I'm B

I'm A

C++11 Polymorphism : Call derived class method from base class pointer

As a conclusion from the comments:

You cannot influence virtual dispatch by overloading the virtual function in a derived class.

Overload resolution and virtual dispatch are orthogonal and the former happens before the latter.

So what you can do is declare multiple overloads, which are individually virtually dispatched.

In your case in the question this simply requires adding the int overload as a pure virtual to A:

class A
{
public:
virtual void setup()=0;
virtual void callFunction(std::string, ...)=0;
virtual void callFunction(std::string, int)=0;
};

To make sure that virtual function implementations are matched properly to these overloads, you should add the override specifier to all the implementations in the derived classes, e.g.:

void callFunction(std::string str, int i) override { std::cout<<"\nC::callFunction("<<str<<") = "<<i<<"\n"; };

If you need to support more argument types, simply add another pure virtual overload to A and implement it somewhere in the inheritance hierarchy.

Is there a way to call derived class functions with base class pointer without virtual

Since I could not get any answer from anyone, let me float an option here which I have thought of. This might be a hack though. I am open for correction/comments and criticism as well. :)

The deal is to do reinterpret_cast in the base class functions.

#include <iostream>
#include <vector>

bool preState = true;
class Derived;
class Base;

class Base {
public:
unsigned char a;
int b;
Base() : a('a'), b (2) { };
unsigned char get_a() const;
int get_b() const;
} __attribute__ ((__packed__)) ;

class __attribute__ ((__packed__)) Derived : public Base {
public:
unsigned char c;
int d;
Derived() : c('c'), d(4) { };

unsigned char get_a() const;
int get_b() const;
};

unsigned char Base::get_a() const {
if (preState) {
return a;
} else {
const Derived* d = reinterpret_cast<const Derived*>(this);
return d->get_a();
}
}

int Base::get_b() const {
if (preState) {
return b;
} else {
const Derived* d = reinterpret_cast<const Derived*>(this);
return d->get_b();
}
}

unsigned char Derived::get_a() const {
return c;
}

int Derived::get_b() const {
return d;
}

int main() {
std::vector<Base*> bArray;
bArray.push_back(new Base());
bArray.push_back(new Base());

std::vector<Base*>::iterator bArrayIt = bArray.begin();
for (; bArrayIt != bArray.end(); ++bArrayIt) {
std::cout << (*bArrayIt)->get_a() << " ";
std::cout << (*bArrayIt)->get_b() << std::endl;
}

preState = false;

std::vector<Base*> dArray;
bArrayIt = bArray.begin();
for (; bArrayIt != bArray.end(); ++bArrayIt) {
// Write copy constructor in Derived class which copies everything from
// base object to Derived object
Base* b = new Derived();
dArray.push_back(b);
}

std::vector<Base*>::iterator dArrayIt = dArray.begin();
for (; dArrayIt != dArray.end(); ++dArrayIt) {
std::cout << (*dArrayIt)->get_a() << " ";
std::cout << (*dArrayIt)->get_b() << std::endl;
}

}

The output of this would be:

a 2 // Base class get_a() and get_b()
a 2 // Base class get_a() and get_b()
c 4 // Derived class get_a() and get_b()
c 4 // Derived class get_a() and get_b()

Calling derived class method from base class pointer

You can declare your pointer as Child type. You will still be able to pass it to function expecting a Parent pointer.

Other solution involves using dynamic_cast<Child>(pa) although this is often seen as bad design to need this because it defeats what polymorphism is supposed to accomplish.

Calling derived class through base class function pointer

Yes, it's guaranteed to work. From [expr.static.cast]:

A prvalue of type “pointer to member of D of type cv1 T” can be converted to a prvalue of type “pointer
to member of B of type cv2 T”, where B is a base class (Clause 10) of D, if cv2 is the same cv-qualification
as, or greater cv-qualification than, cv1.70 If no valid standard conversion from “pointer to member of B of
type T” to “pointer to member of D of type T” exists (4.11), the program is ill-formed. The null member
pointer value (4.11) is converted to the null member pointer value of the destination type. If class B contains
the original member, or is a base or derived class of the class containing the original member, the resulting
pointer to member points to the original member.

In this case, we're converting a pointer to member of CDerived of type void() to a poitner to member of CBase ov type void(). CBase is a base of the class containing the original member, so the resulting pointer points to the original member.

From [expr.mptr.oper]:

Abbreviating pm-expression.*cast-expression as E1.*E2, E1 is called the object expression. If the dynamic
type of E1 does not contain the member to which E2 refers, the behavior is undefined.

In this case, pointer pointers to the original member. base has that member. So this is fine.


Note that in your example, base is actually a CDerived*. It would be just as valid to write:

CDerived d;
CBase* b = &d;

(b->*pointer)(); // ok - the dynamic type of b contains the member to which pointer refers

Calling Derived class function from a Base class pointer after typecasting it to Derived class pointer

I am not sure, why & how the line b->B() works? [..] the Base class object itself should not have that function in memory

You're right! It doesn't work!

(Well, functions aren't stored "in memory", but…)

The call is invalid. The static_cast says "I promise that this Base* points to a Derived". That promise was broken.

The program has undefined behaviour. That can in practice mean that things "appear" to work, especially if no member variables were touched by the non-existent function...



Related Topics



Leave a reply



Submit