hello all
hello all

Reputation: 252

C++: Inheriting functions that return base class pointer

I have a base class Base and a class that inherits it called Derived. Class Base has a virtual function returnPtrToSelf() that returns a pointer to itself. Derived has its original member function derivedFunc() which Base has not.

#include <iostream>

class Base {
public:
    virtual Base* returnPtrToSelf() {
        return this;
    }
};

class Derived : public Base {
public:
    void derivedFunc() {
        std::cout << "i am derived" << std::endl;
    }
}

int main() {
    Derived d;
    d.derivedFunc();                                   // works
    d.returnPtrToSelf()->derivedFunc();                // ERROR
    ((Derived*)d.returnPtrToSelf())->derivedFunc();    // works
}

The error will not go away unless I implement Derived's own returnPtrToSelf() that returns a Derived*.

I am making a lot of derived classes and think it is tedious to implement an original version of this function for each derived class. Is there a more convenient way of fixing that error other than this tedious way?

Upvotes: 1

Views: 2150

Answers (2)

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

"I am making a lot of derived classes and think it is tedious to implement an original version of this function for each derived class. Is there a more convenient way of fixing that error other than this tedious way?"

I'd say that's a classical case to use the Template Method Pattern:

 class Base {
 public:
     void func() {
         funcImpl();
     }
     virtual ~Base() {}
 protected:
     Base() {}
     virtual void funcImpl() = 0;
 };

 class DerivedA : public Base {
 public:
     DerivedA() {}
 protected:
     void funcImpl() {
         // DerivedA special implementation
     }
 };

 class DerivedB : public Base {
 public:
     DerivedB() {}
 protected:
     void funcImpl() {
          // DerivedB special implementation
     }
 };

Call in main would look like

int main() {
    DerivedA dA;
    DerivedB dB;
    dA.func();
    dB.func();
}

This is especially useful, if every class derived from Base should contribute some specialized piece for some more complex logic going on in Base::func().


This could be achieved in a similar way using a templated base class (without need for the vtable overhead), and merely encapsulating the cast applied in your main() function:

 template<typename Derived>
 class Base {
 public:
     void func() {
         static_cast<Derived*>(this)->funcImpl();
     }
 protected:
     Base() {}
 };

 class DerivedA : public Base<DerivedA> {
 public:
      DerivedA {}
 protected:
      friend class Base<DerivedA>;
      void funcImpl() {
          // DerivedA special implementation
      }
 }; 

 class DerivedB : public Base<DerivedB> {
 public:
      DerivedB {}
 protected:
      friend class Base<DerivedB>;
      void funcImpl() {
          // DerivedB special implementation
      }
 }; 

This is also well known as the CRTP -> Curiously Recurring Template Pattern.

Upvotes: 0

Barry
Barry

Reputation: 302718

No, there isn't. If derivedFunc is really something that anything that inherits from Base should support, then that should be reflected in Base:

struct Base {
    virtual void func() = 0;
};

struct Derived : Base {
    void func() override { std::cout << "i am derived" << std::endl; }
};

Base* b = new Derived;
b->func();

If derivedFunc is only applicable to a Derived, then it wouldn't make any sense to be able to access it from Base anyway. What if Base were a AnotherDerived instead? In those cases where you really need to call derivedFunc, just have your functions take a Derived* (or Derived&) instead of a Base* (or Base&).

As a last resort, if there's really some case where you absolutely need to call derivedFunc on a Derived uniquely, then there's always:

void maybeCallDerivedFunc(Base* b) {
    if (auto d = dynamic_cast<Derived*>(b)) {
        d->derivedFunc();
    }
}

Upvotes: 1

Related Questions