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.
Related
I currently trying to understand the name hiding thing in C++ inheritance.
I've read this on C++ primer plus, page 744
In short, redefining inherited methods is not a variation of overloading. If you redefine a function in a derived class, it doesn't just override the base class declaration with same function signature. Instead, it hides all base class methods of the same name, regardless of the argument signatures.
So I tried, here is my two classes, Base, and Derived
class Base{
public:
Base(){
cout << "Base::Base() called\n";
}
virtual ~Base(){}
virtual void output(int x){
cout << "Base::output(int x) called\n";
}
virtual void output(double x){
cout << "Base::output(double x) called\n";
}
virtual void output(char x){
cout << "Base::output(char x) called\n";
}
virtual void output(string x){
cout << "Base::ouput(string x) called\n";
}
};
class Derived : public Base{
public:
Derived():Base(){
cout << "Derived::Derived() called\n";
}
virtual ~Derived(){}
virtual void output(string x){
cout << "Derived::ouput(string x) called\n";
}
};
According to the book, void Base::output(string x) will be redefined, and all other member functions having the same name will be hidden.
But the following two codes tells different stories.
Derived* x = new Derived();
x->output(7);
This code cannot compile as expected, the error message is
No viable conversion from 'int' to 'string'
But if I do like this,
Base* x = new Derived();
x->output(7);
It magically worked, and given following output:
Base::Base() called
Derived::Derived() called
Base::output(int x) called
Why this could happen, does the pointer type really influence the lookup?
Btw, this was on Xcode.
For this code:
Derived* x = new Derived();
x->output(7);
The compiler will first attempt to resolve the function and it sees that Derived has a function called output. Once it finds this, the compiler will not look any further. Then it will resolve the arguments and see that the argument is incorrect and fail.
Either way late binding does not apply here since you are using the Derived class pointer to access a function in the base class. You would have to up-cast.
For this code:
Base* x = new Derived();
x->output(7);
The compiler sees that x is Base type which has the function with the argument of an int. The compiler resolved the function and is set. If you were overriding the function for polymorphic behavior this would the appropriate usage.
Note that you can call x->output("yes"); and the correct function will be called; which would be the Derived version. Here is where the vtable is used.
For the reason why the compiler does this look into the "Fragile base class problem".
When you use
Base* x = new Derived();
x->output(7);
The functions in Derived are not looked up at compile time. Only the functions in Base are looked up at compile time. Hence, it works.
When
x->output(7);
is processed, the only thing we know about type of x is that it is a Base*. The fact that it really points to a Derived object is not taken into account at compile time. At compile time, that call gets resolved to Base::outout(int). Since Base::output(int) is not overridden in Derived, Base::output(int) is executed at run time too. Had there been a Derived::output(int), it would have been executed at run time.
Yes, the pointer type influences the lookup - that's the whole point of having a type. When you define a Base*, all the compiler knows is that it will point to an object of type Base, the possibility of a Derived isn't even considered.
I read about virtual functions but i am not able to clear the concept.
In the below mentioned example.We are creating a base pointer and assigning base object first and calling function is base class and later assigning derived object and calling its function. Since we have already mentioned which objects will be assigned does not compiler know which object function to call during compilation? I did not get why the decision will be delayed till run time. Am i missing something here.?
#include <iostream>
using std::cout;
using std::endl;
// Virtual function selection
class Base
{
public:
virtual void print() const
{
cout << "Inside Base" << endl;
}
};
class Derived : public Base
{
public:
// virtual as well
void print() const
{
cout << "Inside Derived" << endl;
}
};
int main()
{
Base b;
Derived f;
Base* pb = &b; // points at a Base object
pb->print(); // call Base::print()
pb = &f; // points at Derived object
pb->print(); // call Derived::print()
}
In your particular case, the compiler could potentially figure out the type of the objects being pointer at by the base class pointer. But the virtual dispatch mechanism is designed for situations in which you do not have this information at compile time. For example,
int n;
std::cin >> n;
Base b;
Derived d;
Base* pb = n == 42 ? &b : &d;
Here, the choice is made based on user input. The compiler cannot know what pb will point to.
Since we have already mentioned which objects will be assigned does not compiler know which object function to call during compilation? I did not get why the decision will be delayed till run time.
In this very specific, contrived case, your compiler can optimise out all the polymorphism, yes.
Am i missing something here.?
The imagination to realise that the vast majority of code in real life is not this simple. There are infinitely many C++ programs for which the compiler does not have enough information to perform this optimisation.
As per my understanding, the compiler will just look at the reference type at compile time and bind the function defined and declared in that class. Since the Derived -> print() should be called you have to make the print function virtual in the base class so that the compiler will delay the binding to run time and use the function defined in the derived class.
Due to the fact that it is virtual, it is able to dynamically bind the function to the correct object. This means that the pointer calling the function will call the referenced object's 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).
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.
I'd like to build a factory for my Source-Plugins like that:
class PluginFactory {
public:
PluginFactory(){};
virtual ~PluginFactory(){};
static MySource* getSourceById(int id, ParameterList& pList){
switch (id){
case 1:
return new StringSource(pList);
default:
std::cout << "Unknown PluginId!" << std::endl;
return nullptr;
}
}
};
MySource cannot be abstract like usual in the pattern because it will later be used in a template class.
When I call a method of the returned MySource* I get the method of the superclass MySource instead of the overridden method of the subclass StringSource.
Any ideas how to fix this?
EDIT:
I declared the superclass method as vritual:
MySource{
...
virtual std::streamsize read(char* s, std::streamsize n){
...
}
};
I added the override command to the subclasses' read-Method:
class StringSource: public MySource {
...
std::streamsize read(char* s, std::streamsize n) override
{
...
}
};
But it still uses the superclass method. There has to be another reason...
Btw. I put the Source-Class into a boost::iostream::filtering_istream like this:
MySource* source = PluginFactory::getSourceById(1, pluginList[0].second);
boost::iostreams::filtering_istream in;
in.push(*source);
So I don't call the read-method myself.
The problem is this:
in.push(*source);
According to the documentation, this will copy the argument. Since your base class is copyable and not abstract, you encounter the slicing problem where only the base sub-object is copied.
You should be able to fix it by passing a reference wrapper instead:
in.push(std::ref(*source));
I would suggest that you make the base class abstract (or at the very least uncopyable), to prevent the possiblity of slicing. I don't understand your reason for not making it abstract; but whatever requires it to be concrete sounds scary and error-prone.
UPDATE: Since you made it concrete just so you could pass it to this function, you should make it abstract again, and pass a reference wrapper instead.
When I call a method of the returned MySource* i get the method of the superclass MySource instead of the overridden method of the subclass StringSource.
I'm not sure this will work (without seeing any relevant code), but it sounds like you need to declare your superclass method (the one you call) as virtual, so that the compiler knows to run the overridden version (in this case, of StringSource), rather than the superclass version.
Hope this helps!
The method in MySource that you call must be virtual otherwise, the one in the derived class doesn't override but, instead, hides it. For instance,
class Base {
public:
void foo() const { std::cout << "Base::foo()\n"; }
virtual void bar() const { std::cout << "Base::bar()\n"; }
};
class Derived : public Base {
public:
void foo() const { std::cout << "Derived::foo()\n"; } // hides Base::foo
void bar() const { std::cout << "Derived::bar()\n"; } // overrides Base::bar
};
Derived d;
Base& b = d;
d.foo(); // outputs Derived::foo()
b.foo(); // outputs Base::foo()
b.bar(); // outputs Derived::bar()
If you're using C++11, I would advise to use the override keyword in the declaration of Derived::bar():
void bar() const override { std::cout << "Derived::bar()"; }
More precisely, you should use override in the declaration of all derived methods that are meant to override the one in the base class. If you make a mistake and the method in the derived class doesn't override any method in the base, then the compiler will raise an error.
Herb Sutter explains the issues here.
Update: After the OP's addition of more information.
Another possible reason for the issue is as follows. If the base class is copied (e.g. when it's passed to a function by value), then the copy looses information on the dynamic type. For instance, reconsider the example above and these functions:
void call_bar_pass_by_value(Base x) {
x.bar();
}
void call_bar_pass_by_reference(const Base& x) {
x.bar();
}
Then, calling them with b gives:
call_bar_pass_by_value(b); // outputs Base::bar()
call_bar_pass_by_reference(b); // outputs Derived::bar()
I'm not familiar with Boost.Iostreams but looking at the reference documentation of filtering_stream::push() here we can see that this function does take its argument by reference. Hence, the problem that I just described doesn't happen here. However, this function might call another one which call another one ... and one of them might make take the argument by value (or make a copy of it).
The OP states that "MySource cannot be abstract like usual in the pattern because it will later be used in a template class". This suggests that an attempt to copy the object is made.
I don't know what to advise now but just to test my theory above (it doesn't solve the issue) I would temporarily make MySource's copy constructor protected to see whether Boost.Iostreams tries to copy MySource. If so, then the code will fail to compile.