Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling derived class through base class function pointer

Can I call a derived class through a base class function pointer, as shown in the example below?

I understand that my example works, but is it guaranteed to always do so (Assuming the object actually implements the function!), or is this just an idiosyncrasy of the compiler I'm using?

By this logic can't one simply derive all their classes from "CBase" (which in this case is empty so I guess no overhead) and ignore the type in the function pointer?

#include <iostream>

struct CBase
{ 
};

struct CDerived : CBase
{
    void MyFunction()
    {
        std::cout << "Called OK" << std::endl;
    }
};

typedef void (CBase::*FunctionPointer)();


int main()
{
    CDerived* base = new CDerived();

    FunctionPointer pointer = static_cast<FunctionPointer>(&CDerived::MyFunction);
    (base->*pointer)();

    delete base;
}

Example usage scenario: A derived class that takes one or more pointers to "callbacks" in the base class. Can the callback type just be defined using the derived class and thus forgo the need for a template?

like image 964
c z Avatar asked Jun 06 '16 16:06

c z


People also ask

Can we call derived class from base class pointer?

When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function.

Can we create pointer to derived class?

Is it possible that a base class pointer pointing to a Derived class object in C++? Yes, it is possible. Next, we have called functions fun1, fun2, and fun3 with the help of pointer p.

Can be inherited by a derived class from a base class?

The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class. However, inheritance is transitive.

Can we assign derived class object to base?

In C++, a derived class object can be assigned to a base class object, but the other way is not possible.

What is a pointer to a derived class?

A pointer to derived class is a pointer of base class pointing to derived class, but it will hold its aspect. This pointer of base class will be able to temper functions and variables of its own class and can still point to derived class object. Writing code in comment?

What is a derived class in C++?

A derived class is a class which takes some properties from its base class. It is true that a pointer of one class can point to other class, but classes must be a base and derived class, then it is possible. To access the variable of the base class, base class pointer will be used.

Can a pointer of one class point to another class?

It is true that a pointer of one class can point to other class, but classes must be a base and derived class, then it is possible. To access the variable of the base class, base class pointer will be used.

Can We set a base pointer to a derived object?

However, since Derived has a Base part, a more interesting question is whether C++ will let us set a Base pointer or reference to a Derived object. It turns out, we can! #include <iostream> int main() { Derived derived { 5 }; // These are both legal!


2 Answers

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
like image 197
Barry Avatar answered Nov 15 '22 11:11

Barry


You can use this method but casting pointers is not a good practice at all. Method you are using has nothing common with polymorphism. A better way to implement this is using a virtual function and a pure function.

Your base class must have a pure function (pure functions also virtual) and your derived class must implement this function. So you will be able to call this function with base pointer and implementation of your derived class will be called.

#include "stdafx.h"
#include <iostream>

struct CBase
{
    virtual void MyFunction() =0;    // this is a `pure` function. Pure means it's a virtual and may not have implementation. If a class has at least one pure function it means this class is an abstract class
    virtual ~CBase()=default;       //  gotta be or we will have a memory leak during `delete`..
};

struct CDerived : CBase
{
    virtual void MyFunction() override
    {
        std::cout << "Called OK" << std::endl;
    }
};

//typedef void (CBase::*FunctionPointer)();


int main()
{
    CBase* base = new CDerived();

    base->MyFunction();

    delete base;

    system("pause");

    return 0;
}
like image 45
fnc12 Avatar answered Nov 15 '22 11:11

fnc12