C++ member function virtual override and overload at the same time
Asked Answered
M

3

31

If I have a code like this:

struct A {
  virtual void f(int) {}
  virtual void f(void*) {}
};

struct B : public A {
  void f(int) {}
};

struct C : public B {
  void f(void*) {}
};


int main() {
  C c;
  c.f(1);

  return 0;
}

I get an error that says that I am trying to do an invalid conversion from int to void*. Why can't compiler figure out that he has to call B::f, since both functions are declared as virtual?


After reading jalf's answer I went and reduced it even further. This one does not work as well. Not very intuitive.

struct A {
  virtual void f(int) {}
};

struct B : public A {
  void f(void*) {}
};


int main() {
  B b;
  b.f(1);

  return 0;
}
Morphinism answered 25/2, 2009 at 13:4 Comment(0)
B
45

The short answer is "because that's how overload resolution works in C++".

The compiler searches for functions F inside the C class, and if it finds any, it stops the search, and tries to pick a candidate among those. It only looks inside base classes if no matching functions were found in the derived class.

However, you can explicitly introduce the base class functions into the derived class' namespace:

struct C : public B {
  void f(void*) {}
  using B::f; // Add B's f function to C's namespace, allowing it to participate in overload resolution
};
Brophy answered 25/2, 2009 at 13:11 Comment(6)
Might want to add a link to the C++FAQ on function hiding: parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9Holster
@jalf: What's the reason of such compiler's behavior? Why not to search base classes for functions to fit the call ?Mulry
What would be the reason for that? The compiler has to pick some behavior, and this makes sense in some cases, and seems absurd in others. The advantage of this scheme is that you can opt-in to the "continue searching" behavior. But if that was then there would be no way to opt out of it and get this behavior. At the end of the day, the language designers had to make a decision, and they picked this behavior. :)Brophy
@jalf, with mangled names, f(int) and f(void*) will get different names, then how search for f(int) ends at f(void*).? And also it makes sense to match function signature instead of just function name.Rosannarosanne
@null: mangled names don't matter. Only the linker sees mangled names. But the linker doesn't do overload resolution. That's done by the compiler, which sees the original, unmodified, names.Brophy
this is somewhat disappointing in my eyes. i didn't know about this behaviourCarnot
M
-1

Or you could do this:

void main()
{
    A *a = new C();
    a->f(1);  //This will call f(int) from B(Polymorphism)
}
Methodize answered 1/4, 2014 at 21:21 Comment(0)
P
-6

Well I think first of all you did not understand what virtual mechanism or polymorhism. When the polymorphism is achieved only by using object pointers. I think you are new to c++. Without using object pointers then there is no meaning of polymorphism or virtual keyword use base class pointer and assign the desired derived class objects to it. Then call and try it.

Picker answered 22/10, 2009 at 6:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.