Timur
Timur

Reputation: 305

How to inherit some candidates of polymorphic function?

I want to define a function in a base class and a function with the same name and another signature in a subclass like this:

class A {
public:
  void foo () {}
};

class B : public A {
public:
  void foo(int x) {}
};

int main() {
  B b;
  b.foo();
}

But it causes compile error: no matching function for call to ‘B::foo()’. If I comment foo definition in class B, it compiles. How to solve the problem?

What I really want is to define a polymorhic interface in a base class and redefine semantic in child classes.

UPD: Thanks, the answers worked for this example. But it doesn't seem to work with templates: sort.h

...
class Sort {
public:
  template <typename TArr>
  static TArr& sort(TArr& array) { return sort(array, array.size()); }
};

class BubbleSort : public Sort { // add inheritance
public:
  using Sort::sort;
  template <typename TArr>
  static TArr& sort(TArr& array, size_t len) {
     ...
  }
};

test.cpp

...
int main () {
  ...
  std::array<int, 5> test_array {3, 2, 5, 1, 4};
  BubbleSort::sort(test_array)
  ...
}

When I run this, I get:

sort.h: In instantiation of ‘static TArr& Sort::sort(TArr&) [with TArr = std::array<int, 5ul>]’:
test.cpp:9:30:   required from here
sort.h:17:47: error: no matching function for call to ‘Sort::sort(std::array<int, 5ul>&, std::array<int, 5ul>::size_type)’
   static TArr& sort(TArr& array) { return sort(array, array.size()); }
                                               ^
sort.h:17:16: note: candidate: template<class TArr> static TArr& Sort::sort(TArr&)
   static TArr& sort(TArr& array) { return sort(array, array.size()); }
                ^
sort.h:17:16: note:   template argument deduction/substitution failed:
sort.h:17:47: note:   candidate expects 1 argument, 2 provided
   static TArr& sort(TArr& array) { return sort(array, array.size()); }

Why does it happen?

UPD: Got that.

Upvotes: 0

Views: 40

Answers (3)

Edgar Rokjān
Edgar Rokjān

Reputation: 17483

Function f from the derived class simply hides all the functions with the same name from the base class.

To solve it you can use a using-declaration:

class B : public A {
public:
  using A::foo;
  void foo(int x) {}
};

Upvotes: 1

AlexD
AlexD

Reputation: 32586

But it causes compile error: no matching function for call to ‘B::foo()’

Try using-declaration:

class A {
public:
    void foo() {}
};

class B : public A {
public:
    using A::foo;
    void foo(int x) {}
};

What I really want is to define a polymorphic interface in a base class and redefine semantic in child classes.

Well, you should make the base class function virtual an have the same parameters when override it. Otherwise, how the subclass function is supposed to be called via a reference/pointer to the base class?

Upvotes: 2

Jerry Coffin
Jerry Coffin

Reputation: 490623

Without virtual, the A::foo() doesn't define a polymorphic interface.

Anyway, you can make A::foo() visible via B with a using declaration:

class B : public A {
public:
  using A::foo;
  void foo(int x) {}
};

This provides polymorphism to the extent that you accept function overloading as polymorphism--i.e., A::foo() and B::foo() form an overload set, and the compiler chooses which to call based on the parameter(s) you pass (if any), the same way as if B contained two overloaded functions (with the same signatures as the existing A::foo and B::foo).

Upvotes: 2

Related Questions