1

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?

5
  • 1
    What about using a static_cast<Derived*>(d.returnPtrToSelf()) instead? Base doesn't declare any function member derivedFunc(), thus you can't access it via a Base* pointer. Commented Jul 10, 2015 at 16:35
  • @πάνταῥεῖ That is essentially what they did in the last line (except with a C-style cast) Commented Jul 10, 2015 at 16:36
  • If you are making lots of derived classes which have methods that are not in the base, and you want to call those methods, your code will be tedious no matter what. To avoid tedium, re-design the code. Commented Jul 10, 2015 at 16:39
  • Could CRTP help here? ...though, what's wrong with simply using the address-of operator? Commented Jul 10, 2015 at 16:46
  • @celticminstrel Yes, CRTP would be merely the static polymorphism solution of what I've been describing in my answer. The OP should refactor their code. Commented Jul 10, 2015 at 16:49

2 Answers 2

1

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();
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

"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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.