Daniel Goldfarb
Daniel Goldfarb

Reputation: 7714

C++ force implementation of method in child class but with a different signature

Is there a way to force implementation of a method in a child class where the implementation will have a different signature for each derived class?

I know I can do this, using pure virtual:

class Base {
  public:
   virtual void getValue(string& s) = 0;
}

class Derived : public Base {
  public:
   void getValue(string& s);
}

Above, pure virtual getValue in the base class forces the derived class to implement getValue. But what I really want to do is something like this: Force each derived class to implement getValue() but each with a different signature:

class Base {
  public:
   void getValue() = 0;
}

class Derived_A : public Base {
  public:
   void getValue(string& s);
}

class Derived_B : public Base {
  public:
   void getValue(int *j);
}

The problem with the above is that, due to name mangling, each signature is effectively a different function, and thus Derived_A and Derived_B inherit getValue() = 0 and the compiler thinks that they also are abstract.

I've been playing around with some different ways to do this, but it appears to me there is no way to do it. I'm thinking I should simply not declare getValue in the Base class and then just make sure each derived class implements their version of it.

Upvotes: 1

Views: 2492

Answers (2)

R Sahu
R Sahu

Reputation: 206667

If use of CRTP would work for you, you can use:

#include <string>

template <typename TypeSelector>
class Base {
  public:
     using type = typename TypeSelector::type;
     virtual void getValue(type t) = 0;
};

struct TypeSelector_A {
   using type = std::string&;
};

class Derived_A : public Base<TypeSelector_A> {
   public:
      void getValue(std::string& s) { /* Add real implementation */ }
};

struct TypeSelector_B {
   using type = int*;
};

class Derived_B : public Base<TypeSelector_B> {
   public:
      void getValue(int* j) { /* Add real implementation */ }
};

int main()
{
   Derived_A a;
   Derived_B b;
}

Upvotes: 5

Slava
Slava

Reputation: 44268

But what I really want to do is something like this: Force each derived class to implement getValue() but each with a different signature

The whole point of having virtual function (abstract or not) is that you can use it with pointer or reference to the base class which means you would use signature of the function from the base class. With that having what you want is completely useless. What you want can be implemented by returning std::variant or std::any with every virtual function in tree so keeping signature the same.

You should think how would you use such concept if it would be possible. If you think somethink like this:

void foo( Base *b ) {
    if( auto *d = dynamic_cast<Derived_A *>( b ) ) {
       std::string str;
       d->getValue( str );
       ...
    }
    if( auto *d = dynamic_cast<Derived_B *>( b ) ) {
       int i = 0;
       d->getValue( &i );
       ...
    }
}

then getValue() does not need to be virtual, you only need vritual destrictor in Base. But this is considered bad design.

Upvotes: 1

Related Questions