Hide, overload or overwrite in C++ - c++

Then I have a question again. something like this:
#include <iostream>
using namespace std;
class Base
{
public:
void foo()
{
cout<<"Base."<<endl;
}
};
class Derive:public Base
{
public:
void foo()
{
cout<<"Derive."<<endl;
}
};
int main()
{
Derive d;
Base *pb=&d; //attention here
pb->foo(); //ateention here
system("pause");
return 0;
}
And the output is "Base.". Then the function rules are't work, I am confused about this, could you help me? Thanks.

Since foo is not virtual, the function called is based on the static type (i.e., the type the pointer is declared to point at) rather than the dynamic type (the type of object to which the pointer currently refers).
There are also some trickier cases to consider. One point (on which some of the other answers are actually somewhat misleading) is that it's not really just the function name that matters, but the entire function signature. For example:
#include <iostream>
struct base {
virtual void foo() {
std::cout << "base::foo";
}
};
struct derived : base {
virtual void foo() const {
std::cout << "derived::foo";
}
};
int main(){
base *b = new derived;
b->foo();
}
Here foo is qualified as virtual in both the base and (seemingly redundantly the) derived classes, but the call b->foo() still prints out base::foo.
The const added to the signature of derived::foo means it no longer matches the signature of base::foo, so instead of overriding the virtual function, we still end up with two separate functions with the same name, so derived::foo hides base::foo, but doesn't override it. Despite the virtual qualification, we get static binding, so b->foo(); invokes the base function rather than the derived, even though b points to an object of the derived type.
As Tony D pointed out in a comment, C++11 added a new wrinkle to the language to help ensure against this happening. When you want to override a base class function, you can add the identifier override to the function in the derived class:
struct derived : base {
virtual void foo() const override {
std::cout << "derived::foo";
}
};
With this, if there's a difference in function signature (as in the cases shown here), the compiler will produce an error message alerting you to the fact that derived::foo is marked as override, but doesn't actually override a function from the base class. This was, however, added in C++11, so if you're using an older compiler this feature may not be implemented (though thankfully, compilers that don't implement it are quickly fading into oblivion).
Correcting the signature in the base class to:
virtual void foo() const // ...
...will let the code compile, and produce the correct results.

Function Base::foo is non-virtual. It is called because the pointer to the base class is used.
If you change the code like this:
class Base
{
public:
virtual void foo() // add virtual
{
cout<<"Base."<<endl;
}
};
the output should be "Derived".

Judging by the title of your question, I take it that you don't fully understand when functions get hidden, overloaded, and overwritten.
Sample code 1:
struct Base
{
void foo()
{
}
};
struct Derive: public Base
{
void foo()
{
}
};
int main()
{
Derive d;
Base *pb=&d;
d.foo(); // Resolves to Derived::foo()
pb->foo(); // Resolves to Base::foo()
return 0;
}
Why does d.foo() call Derived::foo() and pb->foo() call Base::foo()?
The answer to that question lies in the steps the compiler takes to resolve those function bindings.
Given an object of type T and a function name f, the compiler looks up the functions named f in T. If it finds only one function named f, the search for functions stops there. If it finds more than one function, it attempts overload resolution from the set of functions found in T.
If it does not find any functions named f in T and T has a base class, it tries the above logic in T's base class. If T does not have any base classes, the compiler reports an error.
Coming to the objects of the example code...
When processing the function call d.foo(), the compiler looks for foo in Derived. It finds one match there and it stops. Since the Derived::foo() is not a virtual function, the binding is done at compile time. At run time, Derived::foo() is called.
When processing the function call pb->foo(), the compiler looks for foo in Base. It finds one match there and it stops. Since the Base::foo() is not a virtual function, the binding is done at compile time. At run time, Base::foo() is called.
Sample code 2:
struct Base
{
void foo(int i)
{
}
};
struct Derive: public Base
{
void foo()
{
}
};
int main()
{
Derive d;
Base *pb=&d;
d.foo(); // Resolves to Derived::foo()
d.foo(10); // Compiler error.
pb->foo(10); // Resolves to Base::foo(int)
pb->foo(); // Compiler error.
return 0;
}
Why does the compiler produces the errors here?
When processing the function call d.foo(10), the compiler looks for foo in Derived. It finds one match there and it stops. It tries to use that function but the function's signature does not match the calling code. Hence, it is a compiler error.
When processing the function call pb->foo(), the compiler looks for foo in Base. It finds one match there and it stops. It tries to use that function but the function's signature does not match the calling code. Hence, it is a compiler error.
Once the compiler finds a foo in Derived it does not go searching for a matching foo in Base.
In this case, you can think of Derived::foo to be completely hiding Base::foo.
Sample code 3:
struct Base
{
void foo()
{
}
};
struct Derive: public Base
{
void foo()
{
}
void foo(int )
{
}
};
int main()
{
Derive d;
d.foo(); // Resolves to Derived::foo()
d.foo(10); // Resolves to Derived::foo(int)
Base *pb=&d;
pb->foo(); // Resolves to Base::foo()
pb->foo(10); // Compiler error.
return 0;
}
When processing the function calls d.foo() and d.foo(10), the compiler looks for foo in Derived. It finds couple of matches there and it stops. Then it tries overload resolution. It is able to find a match for both versions. Since neither of the Derived::foo()s is a virtual function, the binding is done at compile time.
When processing the function calls bp->foo() and bp->foo(10), the compiler looks for foo in Base. It finds couple of matches there and it stops. Then it tries overload resolution. It is able to find a match for the first versions but not the second version. It generates an error for the second call.
Here Derived::foo not only hide Base::foo but also there are two overloaded versions of Derived::foo.
Sample code 4:
struct Base
{
virtual void foo()
{
}
void foo(int)
{
}
};
struct Derive: public Base
{
void foo()
{
}
void foo(int )
{
}
};
int main()
{
Derive d;
d.foo(); // Resolves to Derived::foo()
// But Derived:foo() gets called at run time.
d.foo(10); // Resolves to Derived::foo(int)
// But Derived:foo(int) gets called at run time.
Base *pb=&d;
pb->foo(); // Resolves to Base::foo()
// But Derived:foo() gets called at run time due to
// function overwritting.
pb->foo(10); // Resolves to Base::foo(10)
// Base:foo(int) gets called at run time.
return 0;
}
This includes function hiding, function overloading, and function overwritting.
Derived::foo hides Base::foo.
Derived::foo() and Derived::foo(int) are overloaded.
Base::foo() and Base::foo(int) are overloaded.
Base::foo() is overwritten by Derived::foo().
I hope that clears up some of your doubts.

You see this behavior because foo() is not declared as virtual in Base. In C++, member functions are non-virtual by default. You must explicitly declare a function as virtual in order to take advantage of dynamic dispatching and polymorphism.

There's no overloading or overwriting that's going on in this code. Base::foo is being called rather than Derive::foo because there hasn't been any specification by the programmer to use dynamic binding for the name foo. If the virtual-specifier isn't provided, the compiler finds the function based on the static type of the object on which it is called, rather than the type it may point to refer to. This is known as static binding, and it's done at compile-time.
If the virtual-specifer is used, the name of the function is looked up at runtime and called based on the runtime type of the object.
As an aside, your base class needs a virtual destructor for the same reason written above. If you have a Base class pointer that points to Derive deleting that pointer will only call the base class destructor rather than both the base and derived.

Related

c++ polymorphic method defined in derived class matches type that should match to the parent

I'm experimenting with this code
class Base
{
public:
virtual void foo(int) {
// void foo(int) {
cout << "int" << endl;
}
};
class Derived : public Base
{
public:
void foo(double) {
cout << "double" << endl;
}
};
int main()
{
Base* p = new Derived;
p->foo(2.1);
Derived d;
d.foo(2); // why isn't this double?
return 0;
}
It's also available in online editor here https://onlinegdb.com/s8NwhfG_Yy
I'm getting
int
double
I don't understand why d.foo(2) calls the double version. Since Derived inherits the int method and has its own double method, wouldn't polymorphism dictate that 2 be matched to the parent? Thanks.
Polymorphism as in calling virtual methods is orthogonal to symbol and overload resolution. The former happens run-time, the rest at compile-time.
object->foo() always resolves the symbol at compile-time - member variable with overloaded operator() or a method. virtual only delays selecting "the body" of the method. The signature is always fixed, including the return value of course. Otherwise the type system would break. This is one of the reasons why there cannot be virtual function templates.
What you are actually experiencing is name hiding and overload resolution.
For Base* p; p->foo(2.1), the list of possible symbol candidates is only Base::foo(int). The compiler cannot know that p points to Derived (in general) because the choice must be done at compile time. Since int is implicitly convertible to double, foo(int) is chosen. Because the method is virtual, if Derived were to provide its own foo(int) override, it would have been called instead of Base::foo(int) at run-time.
For Derived*d; d->foo(2), the compiler first looks for symbol foo in Derived. Since there is foo(double) which is valid as foo(2), it is chosen. If there was no valid candidate, only then the compiler would look into base classes. If there was Derived::foo(int), possibly virtual, the compiler would choose this instead because it is a better match.
You can disable the name hiding by writing
class Derived: public Base{
using Base::foo;
};
It injects all Base::foo methods into Derived scope. After this, Base::foo(int) (now really Derived::foo(int)) is chosen as the better match.
Read Overload resolution. The answer is in Details:
If any candidate function is a member function (static or non-static), but not a constructor, it is treated as if it has an extra parameter (implicit object parameter) which represents the object for which they are called and appears before the first of the actual parameters.
The selecting between the methods void foo(int) and void foo(double) is happening like between the functions void foo(Base, int) and void foo(Derived, double). The second function while calling d.foo(2) is ranked higher.
If you add using Base::foo; in Derived, the resolution will be performed between three functions void foo(Base, int), void foo(Derived, int) and void foo(Derived, double), and int will be printed.

Inline virtual function when called from another virtual function?

I have a class with two virtual member functions: foo and wrapper. foo is short and fast, and wrapper contains a loop that calls foo many times. My hope is that there is some way to inline the calls to foo inside the wrapper function, even when called from a pointer to an object:
MyClass *obj = getObject();
obj->foo(); // As I understand it, this cannot be inlined. That's okay.
obj->wrapper(); // Nor will this. However, I hope that the machine code
// for the wrapper function will contain inlined calls to
// foo().
Essentially, I want the compiler to generate multiple versions of the wrapper function -- one for each possible class -- and inline calls to the appropriate foo, which should be possible since the object type is determined before picking which wrapper function to execute. Is this possible? Do any compilers support this optimization?
Edit: I appreciate all of the feedback and answers so far, and I may end up picking one of them. However, most responses ignore the last part of my question where I explain why I think this optimization should be feasible. That is really the crux of my question and I am still hoping someone can address that.
Edit 2: I picked Vlad's answer since he both suggested the popular workaround and partially addressed my proposed optimization (in the comments of David's answer). Thanks to everyone who wrote an answer -- I read them all and there wasn't a clear "winner".
Also, I found an academic paper that proposes an optimization very similar to what I was suggesting: http://www.ebb.org/bkuhn/articles/cpp-opt.pdf.
In certain cases, compiler can determine the virtual dispatch behavior in compile-time and perform non-virtual function invocation or even inline the function. It can only do that if it can figure out that your class is the "top" in inheritance chain or those two functions are not otherwise overloaded. Oftentimes, this is simply impossible, especially if you don't have late time optimization enabled for the whole program.
Unless you want to check the results of your compiler's optimizations, your best bet would be not to use a virtual function in the inner loop at all. For example, something like this:
class Foo {
public:
virtual void foo()
{
foo_impl();
}
virtual void bar()
{
for (int i = 0; i < ∞; ++i) {
foo_impl();
}
}
private:
void foo_impl() { /* do some nasty stuff here */ }
};
But in that case you clearly give up the idea that somebody may come in, inherit from your class and throw in their own implementation of "foo" to be called by your "bar". They will essentially will need to re-implement both.
On the other hand, it smells a bit like a premature optimization. Modern CPUs will most likely "lock" your loop, predict the exit from it and execute the same µOPs over and over, even if your method is virtually virtual. So I'd recommend you carefully determine this to be a bottleneck before spending your time optimizing it.
No, the function call will not be inlined if performed through a pointer or reference (this includes the this pointer). A new type can be created that extends from your current type and overrides foo without overriding wrapper.
If you want to enable the compiler to inline your function, you must disable virtual dispatch for that call:
void Type::wrapper() {
Type::foo(); // no dynamic dispatch
}
Imagine the following hierarchy:
class Base
{
virtual void foo();
virtual void wrapper();
};
class Derived1: public Base
{
virtual void foo() { cout << "Derived1::foo"; }
virtual void wrapper() { foo(); }
};
class Derived2: public Derived1
{
virtual void foo() { cout << "Derived2::foo"; }
};
Base * p1 = new Derived1;
p1->wrapper(); // calls Derived1::wrapper which calls Derived1::foo
Base * p2 = new Derived2;
p2->wrapper(); // calls Derived1::wrapper which calls Derived2::foo
Can you see the problem? Derived1::wrapper must call Derived2::foo. It can't know until runtime whether it will be calling Derived1::foo or Derived2::foo, so there's no way to inline it.
If you want to insure that inlining is possible, make sure that the function you want to inline isn't virtual. It seems from your description that this might be possible, if every class in the hierarchy reimplements both foo and wrapper. A function doesn't need to be virtual to be overridden.
This is not accurate. virtual functions can be inlined, but only if the compiler knows the static type of the object with certainty - and thus have the guarantee that polymorphism works.
For example:
struct A
{
virtual void foo()
{
}
};
struct B
{
virtual void foo()
{
}
};
int main()
{
A a;
a.foo(); //this can be inlined
A* pa = new A;
pa->foo(); //so can this
}
void goo(A* pa)
{
pa->foo() //this probably can't
}
That said, it appears that in your case this can't happen. What you can do is have another non-virtual function that actually implements the functionality and call it statically, so the call gets resolved at compile-time:
class MyClass
{
virtual void foo() = 0;
virtual void wrapper() = 0;
};
class Derived : MyClass
{
void fooImpl()
{
//keep the actual implementation here
}
virtual void foo()
{
fooImpl();
}
virtual void wrapper()
{
for ( int i = 0 ; i < manyTimes ; i++ )
fooImpl(); //this can get inlined
}
};
or simply Derived::foo() as pointed out by #avakar.
Your function is virtual and its type is not indicate until runtime, so how you expect compiler to inline code of some class into it?
In some similar situation I had 2 functions: foo that is virtual and foo_impl that is normal function and will be called from foo and wrapper

Why is a virtual table required only in case of virtual functions?

From http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/, code such as
class Base
{
public:
virtual void function1() {};
virtual void function2() {};
};
class D1: public Base
{
public:
virtual void function1() {};
};
class D2: public Base
{
public:
virtual void function2() {};
};
generates a virtual table similar to http://www.learncpp.com/images/CppTutorial/Section12/VTable.gif:
The virtual table as above makes sense. After all the objects need a way to call functions, and need to use function pointers to find them.
What I do not understand is why this is only required in case of using virtual functions? I am definitely missing something since a virtual table does not directly depend on virtual functions.
As an example, if the code being used were
class Base
{
public:
void function1() {};
void function2() {};
};
...
Base b;
b.function1();
and there is no virtual table (meaning there is no pointer to where the function resides), how would the b.function1() call resolve?
Or is it that we have a table in this case as well, just that it is not called a virtual table? In that case the question would arise as to why we need a new kind of table for virtual functions?
[If] there is no virtual table (meaning there is no pointer to where the function resides), how would the b.function1() call resolve?
There is a "pointer", inside the compiler as it's parsing and analysing your code. The compiler's the thing that decides where the function will be generated, so it knows how calls to said function should resolve. In concert with the linker, this all happens tidily within the build process.
The only reason that this doesn't work for virtual functions is that which function you call depends on a type known only at runtime; in fact the same function pointers are present verbatim in the virtual table, written there by the compiler. It's just that in this case, there are multiple to choose from, and they cannot be chosen from until long (read: potentially months or even years!) after the compiler ceases to be involved at all.
There's already a good answer, but I'll attempt a slightly simpler (albeit longer) one:
Think of a non-virtual method of the form
class A
{
public:
int fn(int arg1);
};
as equivalent to a free function of the form:
int fn(A* me, int arg1); // overload A
where me corresponds to the this pointer inside the method version.
If you now have a subclass:
class B : public A
{
public:
int fn(int arg1);
};
this is equivalent to a free function like this:
int fn(B* me, int arg1); // overload B
Note that the first argument has a different type to the free function we declared earlier - the function is overloaded on the type of the first argument.
If you now have some code calling fn() it will choose the overload based on the static type (compile time type) of the first argument:
A* p;
B* q;
// ...
// assign valid pointer values to p and q
// ...
int a = fn(p, 0); // will call overload A
int b = fn(q, 0); // will call overload B
The compiler can and will determine the function to call at compile time in each case and can emit assembly code with a fixed function address or address offset. The concept of a runtime virtual table is nonsensical here.
Now, when I said to think of the method version as equivalent to the free function version, you'll find that at the assembly language level, they are equivalent. The only difference will be the so-called mangled name that encodes the type in the compiled function name and distinguishes overloaded functions. The fact that you call methods via p->fn(0), that is, with the first argument before the method name is pure syntactic sugar - you're not actually dereferencing the pointer p in the example, even though it looks like it. You're just passing p as the implicit this argument. So, to continue the above example,
p->fn(0); // will always call A::fn()
q->fn(0); // will always call B::fn()
because fn being a non-virtual method means the compiler dispatches on the this pointer's static type, which it can do at compile time.
Although virtual functions use the same calling syntax as non-virtual member functions, you are in fact dereferencing the object pointer; specifically, you're dereferencing the pointer to the object's class's virtual table.

C++ virtual method overload/override compiler error

I'm writing a little program in C++ and I what to play with polymorphism.
So the code goes like this:
//Base.h
class Base{
public:
void method(const objectType1& stuff1);
//objectType1 is whatever type you what (int, string, ...)
protected:
Base(void);
virtual ~Base(void);
virtual void method(void) = 0;
};
//Derived.h
/*FINAL - DO NOT INHERIT THIS CLASS OR YOU WILL die :)*/
class Derived : public Base{
public:
Derived(void);
~Derived(void);
private:
void method(void);
};
//Main.cpp
int main(){
objectType1 ot1;
//this code works
Base *bd = new Derived;
bd->method(ot1);
//this dosen't
Derived *dd = new Derived;
dd->method(ot1);
// he doesn't call Base::method(const objectType1& stuff1),
// he calls Derived::method(void)
return 0;
}
I've solved the problem by renaming the virtual method void method(void) in something else and all is well.
My questions are:
Why doesn't the compiler know to call the method from the base class?
And why do I see void method(void) in main since it is declared as protected in Base and private in Derived ? (is this some sort of side effect)
Thanks :) .
The member method in the base class is public, which means that any piece of code can call it. Besides being public, it is virtual, which means that the execution will be dynamically dispatched at runtime to the final overrider.
Access to the method is checked statically in the static type of the reference/pointer through which the call is dispatched, even if it will be dynamically dispatched.
On the other hand in the second case, the call is through the derived type, and the access specifier is checked at that level, where the compiler finds the member function to be private and thus complains.
In plain english, when the object is used as a base, it behaves as a base, but when used directly it behaves as derived.
The method definition in Derived hides the definition in Base. To avoid that, add using Base::method; to Derived.
This happens because when calling functions in Derived, the compiler looks into Base only if it didn't fine the name in Derived. Note that it doesn't look for the signature but only for the name in that stage. Overload resolution based on the signature is done only afterwards. This is actually not much different to the following situation:
void function(int);
void function();
int main()
{
void function(); // this declaration hides *both* global declarations
function(3); // error
}
In your case Base plays the role of the global scope and Derived the role of the function scope.
Also note that this is not related to virtaul fgunctions; indeed the same would happen without virtual (except that you then couldn't call Derived's method via a pointer to Base, of course, but would call the Base version instead).

Virtual calls in inheritance

How would i know if call to a function is resolved at compile-time or run-time from any class?
For example - In the following, From Derived class when show() is called, would it be resolved at runtime?
#include <iostream>
using std::ostream;
class Base
{
public:
virtual void show() {
show(); //Call derived class 'show()'
}
};
class Derived : public Base {
public:
void show() {
show(); //Call to itself, Would this call be resolved at run-time?
}
};
ostream& operator <<(ostream &os, Base &obj)
{
obj.Base::show();
return os;
}
int main()
{
Derived D;
cout << D << endl;
}
Whenever you are calling a member function through an object of the concrete type (i.e. no pointer), the static type is known thus the compiler resolves the right function at compile time.
The only time virtual functions are resolved at runtime is when you are calling them on a pointer to an object, using polymorphism.
In your example the calls to show() are made through the "this" pointer and subsequently they would be resolved at runtime. Consider that there could always be a class even further down the inheritance chain that implements show().
The explicitly qualified call "obj.Base::show()" is obviously resolved at compile time.
Whenever the compiler can figure out which overload of your function to call, it will. It is guaranteed to be able to do that when
it has the complete type of the object (e.g. Foo foo; foo.bar();)
you tell it which overload to call (e.g. Foo foo; foo.Bar::bar();)
but it may be able to do that in cases where it's less obvious - i.e. if it can figure out that "this pointer to Foo really always points to Bar". That's called devirtualization and is part of the night goggles an optimizing compiler has. Depending on your compiler, and depending on your real-world code, it may be possible to perform this optimization - and call your function directly without passing through the vtable.
To answer your question, in your code obj.Base::show() is being resolved at compile time because of the explicit call to the Base function. If you want to resolve this at run time then you can use a pointer to the Base and pass to it a pointer to a Derived.
For example:
ostream& operator <<(ostream &os, Base *obj)
{
obj->show();
return os;
}
int main()
{
Derived D;
cout << &D << endl;
}
I am not sure what you are trying to do. From your code it seems that you want to call the derived (polymorphic, resolved at runtime version) from your base class 'show()' function. There is no need for this since the Derived version is automatically called because it is virtual.