Inheritance and Pointers of Base Class - c++

I was going through this Book and I can't wrap my head around this:
if B::f(int) hides A::f(), why does pa1->f(); not give an error?
Doesn't name hiding mean that, the function f() doesn't exist in class B? And if pa1 points to an object of class B then pa1->f(); should result in an error just as b.f() does!
Please explain this, as I can't understand it through the book!
Thanks in advance!
#include <iostream>
using namespace std;
struct A {
virtual void f() { cout << "Class A" << endl; }
};
struct B: A {
void f(int) { cout << "Class B" << endl; }
};
struct C: B {
void f() { cout << "Class C" << endl; }
};
int main() {
B b; C c;
A* pa1 = &b;
A* pa2 = &c;
// b.f();
pa1->f();
pa2->f();
}

It would be an error if you tried to call f() from scope of B. But, you're calling it through a pointer to base class. The name lookup and overload resolution is done based on the static type of the object, A* in this case. From there, f() is visible.

if B::f(int) hides A::f(), why does pa1->f(); not give an error?
Because pa1 points to A, and A has a member called f which can be called like that. In this context, any other class (including B) is irrelevant.
Doesn't name hiding mean that, the function f() doesn't exist in class B?
No. It means that, in the context of B, the only function called f that can be found by unqualified lookup is B::f. It doesn't remove f from any other context, or prevent it from being found by qualified lookup such as b.A::f().
And if pa1 points to an object of class B then pa1->f(); should result in an error just as b.f() does!
The dynamic type is B, so that's the type used (at run time) to call virtual functions. Non-virtual functions are selected by the compiler according to the static type, which is A. In general, the compiler doesn't know the dynamic type; all it knows is that the pointer points to an A or some unknown derived class.

The call pa1->f(); is first routed to object of type A, since pa1 is a pointer to that type. The virtual keyword would re-route the call to type B if there was a function that matches the exact(!!) signature of the call. Since there is no such function in type B, the type A function is executed.
What I mean is that in this case the functions do not "hide" each other because the signature differs. [f(void) vs. f(int)]
EDIT:
To be more clear. f(int) and f(void) are two completely different functions. As different as f(void) to g(int) would be.

Related

Calling a virtual function from within an inherited function?

I've tried to map it out in my head, but honestly I have no idea what's really going on here.
What exactly is happening when I add and remove the virtual keyword from the below example?
#include <iostream>
#include <string>
class A {
public:
A() { me = "From A"; }
void caller() { func(); }
virtual void func() { std::cout << me << std::endl; } // THIS LINE!
private:
std::string me;
};
class B : public A {
public:
B() { me = "From B"; }
void func() { std::cout << me << std::endl; }
private:
std::string me;
};
int main() {
A a;
a.caller();
B b;
b.caller();
return 0;
}
With the virtual keyword, it prints "From A", then "From B".
Without the virtual keyword, it prints "From A", then "From A".
So far, this is the only time I've found a use for virtual functions without pointers being involved. I thought that if the virtual keyword was removed, the compiler would do the standard thing which is to overload the inherited function and end up printing "From A", and "From B" anyway.
I think this is deeper than just the VTable, and that it's more about the way it behaves in particular circumstances. Does B even have a VTable?
The call
func()
is equivalent to
this->func()
so there is a pointer involved.
Still, there's no need to involve pointers to understand the behavior.
Even a direct call of e.g. b.func() has to work as if it's a virtual call, when func is virtual in the statically known type. The compiler can optimize it based on knowing the most derived type of b. But that's a different kind of consideration (optimizations can do just about anything).
Apart from the issue of virtual dispatch, what may bring extra confusion, is that you have two mes, one declared in A and another declared in B. These are two distinct objects.
An object of type B has two data members of type std::string; one on its own, and one incorporated into the subobject of type A. The latter one, though, is not immediately available in the methods of type B because its name is eclipsed by the new me introduced in this class (though you may use a qualified name, A::me to refer to it).
Therefore, even though the bodies of A::func and B::func seem identical, the identifier me used in both of them refers to different members.
In your example, you won't see the difference:
With the virtual function, the compiler will generate a call via the VTable and at runtime, each objects will call the right function for their real class.
With the non virtual function, the compiler determines at compile time the right function to call, based on the objects defined class.
Now try the following, to see the virtual function in action:
A *pa = &b; // pointer to an A: valid as b is a B wich is also an A.
pa -> caller(); // guess what will be called if virtual or not.
No need for pointer to experimenting with virtual functions. You can observe the same effect with references as well:
A& ra = b; // create a reference to an A, but could as well be a parameter passed by reference.
ra.caller();
Virtual functions are useful for polymorphism. The idea is that you work with a general object of a class, but you don't know at compile time, if at runtime the object will really be of this class, or if it will not be a more specialiszed object (inheriting from the class).

Virtual function overloading

Lets say that we have :
Class A
{
public:
virtual void print(){ std::cout<<" A "<<endl; }
}
Class B : public A
{
public:
virtual void print(int x){ std::cout<<" B "<<endl;}
}
I thought that the definition in Class B of function print will hide the function print from class A. But the following code works and prints " A "
int main()
{
A * a = new B;
a->print();
return 0;
}
If I write the main function like this it doesnt work :
int main()
{
B b;
b.print();
return 0;
}
What i Want to know is...in my first main() example I have a B object that calls print()...shouldnt then print() be hidden and have an error like in the second main() example
The member function print() in B is not overriding the print() in A because it has a different signature. Therefore, when calling print() in your first, unedited version of main(), there is only one matching function to call, as pointed out by user juanchopanza: A::print().
EDIT: To summarize:
Polymorphic behavior: If A::print() and B::print() had the same signature, the appropriate print() would be chosen at runtime as long as you reference the object through pointers or references.
Function overloading: Since a class is a scope and functions do not overload across scopes, the functions from base classes are hidden by functions of the same name in a derived class. For this, the type of the variable you are using to refer to your object is the one that matters, not the type of the object itself. Therefore, in your second example you get an error that there is no matching function to call, but in your first example, only one function is in scope.
The issue here is name lookup. In a call like A *a = new B; a->print() the compiler looks at the type of a, which is A*, and looks in the class A for a member function named print. It finds it and it calls it. Similarly, with B *b = new B; b->print(); the compiler looks in class B for a member function named print; it finds print(int), which can't be called with no arguments. And because it found a function named print in B it stops looking; it doesn't go into A to find A::print(). That's name hiding.
The key here is that name lookup starts with the declared type of the object; in these two examples the types are A* and B*, respectively. Lookup does not pay attention to the actual type of the thing that a pointer or reference points to or refers to.
Named overloading functions in a derived class are hiding those from the base class. However, you'll need to use the derived class interface to see so:
B b;
b.print(); // won't work
That is because two print() functions have different signatures. Two functions - print() and print(int) are considered different and cannot be overloaded overridden by each other.
Check your class definitions; the print functions in A and B have different signatures. When you call
a->print();
There's only one function that fits that signature, which is A::print(). If you remove the int parameter from B's definition you should observe the behaviour you're expecting.

when a base class pointer point to a base class object whether the compiler will use dynamic binding?

I know that when use a base class pointer which point to a derived class object to call a virtual function, the compiler will use dynamic binding to call the derived version.
But when use a base class pointer which point to a base class object to call a virtual function, does the compiler use dynamic binding or static binding to call the virtual
function?
For example:
class Base
{
public:
virtual void show()
{
cout << "base class";
}
}
int main()
{
Base *pb; //Base class pointer
Base b; //Base class object
pb = &b;
pb->show(); //Is static binding or dynamic binding?
}
Because My English is very bad, so I want to make my question as simple as possible, but I will describle my question in more detail in follow:
Actually the problem stems from that I am summarizing how to trigger dynamic binding.
At first I summary the trigger condition are:
the function must a virtual function.
must use pointer or reference to call the function.
The two trigger condition cause the problem that I asked:
"when a base class pointer point to a base class object whether the compiler will use dynamic binding?"
I have google for search answer, and I find a fragment (the demo is here):
struct A {
virtual void f() { cout << "Class A" << endl; }
};
struct B: A {
//Note that it not overrides A::f.
void f(int) { cout << "Class B" << endl; }
};
struct C: B {
void f() { cout << "Class C" << endl; }
};
int main() {
B b; C c;
A* pa1 = &b;
A* pa2 = &c;
// b.f();
pa1->f();
pa2->f();
}
The following is the output of the above example:
"Class A"
"Class C"
According to pa1->f() will output Class A, I summary third trigger condition:
3.function in base class must be overridden in the derived class.
Now according to the three trigger condition, when use a base class pointer which point to a base class object to call a virtual function, the compiler will use static binding to call the virtual function, because the virtual is not overridden.
But when use a derived class pointer which point to a derived class object to call a virtual function, it will use dynamic binding, because the virtual is overridden.
It made me very confused.
It can choose whichever, or neither, depending on how smart it is and how well it can detect. The rule is polymorphism must work. How this is achieved is an implementation detail.
If the same end-result can be achieved with both dynamic or static binding, as is the case here, both are valid options for the compiler.
In your case, the function doesn't have to be called at all - the generated code could be just as well identical to code generated by
int main()
{
cout << "base class";
}
I guess it depends on compiler optimization. Compiler might be clever enough to figure out that Base::show is always the one called or it might not. You can look at the disassembly to find out. You can force static-binding with b->Base::show()
Short answer: No. At least in theory not. Because in theory, the compiler does not know wether the pointer points to a Base, a Derived or to YetAnotherDerived object. Therefore it has to apply the same mechanism regardless of the dynamic type of the object.
But: In practise, compilers have optimizers, capable of identifying some use cases where the dynamic type is known. I your case it can detect the aliasing, meaning it knows that pb points to b and that it is a local variable and cannot be changed concurrently, so it knows that in fact you are calling b.show() and will abbreviate the output to reflect that fact and get rid of the virtual dispatch. Similar optimizations are possible e.g. in this code:
auto pb = make_unique<Base>();
pb->show();
But as any optimization it is up to the compiler if it applies them - the standard says virtual dispatch happens even if the pointer points to a Base object, and that's it.

Polymorphism or inheritance?

I have a theoretical question about C++. It was part of the final exam at my university and I want to know why the method f of class B is called, while it should be derived by the base class A. Since it is not virtual shouldn't the A::f() be called?
#include <iostream.h>
#include <stdlib.h>
class A{
public:int f(int x){
cout<< x << " ";
}
};
class B:public A{
public:int f(int y){
A::f(y+1);
}
};
void g(A a, B b) {
a.f(3);
b.f(3);
}
int main()
{
B p;
B q;
g(p,q);
system("PAUSE");
return 0;
}
// result is 3 4
The static type if b in g() is B, thus there is no need for virtual here - the compiler can know [at compile time] you want to invoke B::f(), and that is exactly what he is doing. In here, the class B redefined A's f(), and hides it, so invoking f() from a variable whose static type is B results in invoking B::f()
Note that the virtual keyword allows you to use overriding methods where the static type is the parent's type.
The method g takes two arguments, of type A and B repsectively. Since these are no pointer or reference types, dynamic binding does not apply. The compiler knows at compile time the actual type of the objects, and does a static method call.
virtual methods only apply if you have pointers or references!
The function int f(int) in class B "hides" the function with the same name and signature in its base class.
So, when you call b.f(3);, and the variable b has type B, you are calling B::f.
Virtual functions are only needed if you want b.f(3) to call B::f in cases where the type of the variable b is A&, but the object it refers to has runtime type B. In that situation, the function called would be B::f if A::f is virtual, but A::f is called if non-virtual.
Virtual function calls take the runtime type of objects into account even if they're used via a pointer or reference to a base class. But B b; b.f(3) is a call to B::f regardless of whether A::f even exists, never mind whether it's virtual or non-virtual.
There are 2 things happening here:
You are slicing your object.
Your f() function is not an override because it is not virtual, and really you should not be doing this.
You would overcome the slicing by making the function g take its first parameter by reference. If A was given a protected copy-constructor that would also prevent it, although then you would not be able to copy genuine instances of A.
In this case your function g will always call A::f() even with reference to A because there is no polymorphism. To invoke that you will need to declare A::f() as virtual.
"Non-scientific" explanation:
The function g treats a as if it was an instance of A gets a copy of p as an object of type A(see comments below) , and executes the f from within A. b is treated as an instance of B, where the method B.f overrides A.f, so when b is "looked at" as an instance of B and we execute b.f, the method B.f will be executed, because the A.f is not visible
If you'd like to call A.f using b.f you'd have to cast b to A: ((A)b).f().

Member function hidden in derived class

Please look at the following code:
#include <iostream>
using namespace std;
class A {
public:
A() {};
virtual void foo(double d) { cout << d << endl; }
virtual void foo(double d, int a) = 0;
};
class B : public A {
public:
B() {};
virtual void foo(double d, int a) { cout << d << endl << a << endl; }
};
int main()
{
B b;
b.foo(3.14);
return 0;
}
The compiler (tried g++ and visual c++ 2008) says that there's no function like B:foo(double). The exact message of g++ is:
main.cpp:21: error: no matching function for call to ‘B::foo(double)’
It looks like the effect of hiding rule, but in my opinion the rule should not be used here, since I'm not overriding foo(double) and both foo methods are defined in base class.
I know that I can fix the problem with
using A::foo;
declaration in the derived class B.
Can you explain why the code does not compile and what rules of C++ apply here?
The hiding rule is not about overriding, it is about hiding of names. If the derived class declares a member function, this hides other base class member functions with the same name. This also happens in your case.
Names shadow, not specific functions. Once you make a foo in B, all base foo's (note, by name!) are shadowed.
When the compiler encounters an identifier, the lookup rules kick in and start searching for that identifier. In your concrete situation, with b.foo, the compiler knows that foo must be a member of B or one of its subclasses. The lookup rules state that the compiler must start with the most derived class (considering the static type of the object) and follow up in the hierarchy, and that once the identifier is found in one level only definitions in that level will be considered, it must not keep looking upwards.
B& f(); // might return a B or something derived from B
void test() {
B& b = f(); // static type is B
b.foo(1.0);
}
Regardless of what f returns, the static type is B, so the compiler will lookup in B class and find B::foo(double,int). Since there is no other foo declaration at that level, the compiler must try to match (and fail) the function call with the available method declarations.
The important thing is that the lookup does not look the object but rather looks by type and going upwards, cutting as soon as it encounters the first instance.
Looks perfectly reasonable to me. Although function signature does matter to know what the function is, I can see how this behavior prevents very stupid mistakes.
As ereOn suggested, using directive would be a fair price to pay.