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).
Related
Here are my code
#include <iostream>
using namespace std;
class BaseClass
{
public:
BaseClass() {}
void init(const int object) { cout<<"BaseClass::init"<<endl; }
void run(const int object) { cout<<"BaseClass::run calls =>"; init(object); }
};
class Derived : public BaseClass {
public:
Derived() {}
void init(const int object) { cout<<"Derived::init"<<endl; }
};
int main() {
BaseClass b;
b.init('c');
b.run('c');
Derived d;
d.init(5); // Calls Derived::init
d.run(5); // Calls Base::init. **I expected it to call Derived::init**
}
And here is generated output
BaseClass::init
BaseClass::run calls =>BaseClass::init
Derived::init
BaseClass::run calls =>BaseClass::init
With call d.run(5), Why "BaseClass::init" is being called instead of "Derived::init" ?
I though we need virtual functions only when calling through a pointer.
What is the rationale behind keeping such behavior ?
Why "BaseClass::init" is being called instead of "Derived::init" ?
Because init is a non-virtual member function. To have the desired effect, you need to make init a virtual member function as shown below:
class BaseClass
{
public:
BaseClass() {}
//NOTE THE VIRTUAL KEYWORD HERE
virtual void init(const int object) { cout<<"BaseClass::init"<<endl; }
//other member function here as before
};
Demo
I though we need virtual functions only when calling through a pointer.
Note that the statement init(object); is equivalent to writing
this->init(object); //here `this` is a pointer
When you wrote:
d.run(5);
In the above statement, first the address of object d is implicitly passed as the first argument to the implicit this parameter of member function run. The type of this implicit this parameter is BaseClass* and this happens due to derived to base conversion. Now, the call init(object); is equivalent to this->init(object);. But since init is a non-virtual member function, the call is resolved at compile time meaning the base class init will be called.
Basically when a member function is called with a derived class object, the compiler first looks to see if that member exists in the derived class. If not, it begins walking up the inheritance chain and checking whether the member has been defined in any of the parent classes. It uses the first one it finds. This means for the call d.run(5) the search for a member function named run starts inside the derived class. But since there is no function named run inside derived class, the compiler looks into the direct base class BaseClass and finds the member function named run. So it stops its search and uses this found run member function. And as i said, in your example, init is non-virtual and so the call is resolved at compile time to the base class run.
On the other hand, if we make init to be a virtual member function, then this call will be resolved at run-time meaning the derived class init will be called.
I though we need virtual functions only when calling through a pointer.
No. Thats not right. You need to make a function virtual when you want to enable calling it based on the dynamic type of the object. And once you do have a virtual function you can use pointers or references to make use of the virtual dispatch.
You need to make a method virtual when you want to override it. As BaseClass::run is not overridden by Derived::run, there is no virtual dispatch and calling init from BaseClass::run calls BaseClass::init. If you want to enable virtual dispatch for BaseClass::init you need to declare it virtual.
Further, consider that your code is equivalent to:
void run(const int object) {
cout<<"BaseClass::run calls =>";
this->init(object);
}
this is BaseClass*, hence BaseClass::init is called. You are calling init via a pointer, but that does not matter because init is not virtual. If you want to call init based on the dynamic type of the object, thats exactly what virtual is good for. The "overhead" you refer to in comments is not really overhead, but just the minimum needed to get the behavior you want. If you can change the design and do not need runtime polymorphism you can take a look at CRTP wich is a form of static polymorphism.
I have a Base class pointer pointing to derived class object. The method foo() is public in base class but private in derived class. Base class foo() is virtual. So when i call foo() from Base class pointer, Vptr Table has the address of derived class foo(), BUT its private in Derived class ...so how is it getting called.??
I understand Run time polymorphism and i also understand that the Access specifiers work for compile time and Virtual concept works at run time. So there shall be No Compiler error.
My question is : Is this is a loop hole through which we can call private methods of Derived class ? or Its expected to behave this way.
Any good Explanation for this behavior.
Thanks a lot in advance.
CODE :
class A
{
public:
virtual void foo()
{
std::cout << "In A";
}
};
class B:public A
{
private:
void foo()
{
std::cout << "In B ??? Its Private Method :-( ";
}
};
int main()
{
A* ptr = new B();
ptr->foo();
return 0;
}
It's private method, but since it's virtual - it can be called.
n3690 11.5/1
The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by
the rules for a function that later overrides it.
Why this? Since
n3690 11.5/2
Access is checked at the call point using the type of the expression used to denote the object for which the
member function is called (B* in the example above). The access of the member function in the class in
which it was defined (D in the example above) is in general not known.
Access level is a compile-time concept. The runtime doesn't know if a method was declared private or public. Those are there for your convenience.
This is actually a good coding standard - a virtual method should be ideally public in the base class and private or protected in derived classes. This will force the caller to use the interfaces rather than the actual types (of course, this isn't always practical, but a good thing to take into account).
The concrete type is abstracted away in your case, as it should be. The base method is declared public and you're calling it through a pointer to a base, so it's allowed.
I had a situation where I wanted a friend class to call a private method, then I wanted to make this method virtual so derived a class's method would get called instead - then I of course realised friendship isn't inherited. So we have a situation where the virtual method means the derived class's method should be called, but this method is private so cannot be called. Which has priority?
I tested this on MSVC++ 2008 as follows
#include<iostream>
class Loner;
class Base
{
friend Loner;
private:
virtual void test(){std::cout << "Base" << std::endl;}
};
class Derived : public Base
{
private:
virtual void test(){std::cout << "Derived" << std::endl;}
};
class Loner
{
public:
void test(Base *base){base->test();}
};
int main()
{
Loner loner;
Derived derived;
loner.test(&derived);
}
The output was:
Derived
So it seems that the virtual function "wins" and gives private member access to a non friend - almost friend inheritance!
My question is, does anyone know if this is correct behaviour? When I finally get round to upgrading my compiler version or if I try on GCC might this behaviour change?
Cheers
Phil
§ 11.5/1-2 ([class.access.virt]):
The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it.
Access is checked at the call point using the type of the expression used to denote the object for which the member function is called...
So you're good to upgrade. (There's an example in the actual standard, but I left it out of the quote.)
In effect, what's going on here is that the Base virtual function does the despatch to its overrides. So even though you can't call a Derived override statically (Derived::member), you can still get Base::member to call it for you, if you have access to Base::member.
the call is being made through an object pointer with a 'static' type of Base* - this is the type that access checks are performed against. These access checks occur at compile time. Since Loner is a friend of Base, the compiler is fine with permitting the call to base->test().
However, the dynamic type of the object that the base pointer points to is Derived. At runtime there are no additional access checks - the call is made to the dynamic type, which is dispatch through the normal virtual call mechanism.
I am wondering if it is possible to call a derived class´ function from within a function called by the base constructor (shouldn´t it already be created when the code in the brackets are executed?)
#pragma once
class ClassA
{
public:
ClassA(void);
virtual ~ClassA(void);
void Init();
protected:
short m_a;
short m_b;
virtual void SetNumbers(short s);
};
include "ClassA.h"
#include <iostream>
ClassA::ClassA(void) : m_a(0), m_b(0)
{
Init();
}
ClassA::~ClassA(void)
{
}
void ClassA::SetNumbers(short s)
{
std::cout << "In ClassA::SetNumbers()\n";
m_a = s;
m_b = s;
}
void ClassA::Init()
{
this->SetNumbers(2);
}
#pragma once
#include "ClassA.h"
class ClassB : public ClassA
{
public:
ClassB(void);
virtual ~ClassB(void);
virtual void SetNumbers(short);
int x;
};
#include "ClassB.h"
#include <iostream>
ClassB::ClassB(void)
{
}
ClassB::~ClassB(void)
{
}
void ClassB::SetNumbers(short s)
{
std::cout << "In ClassB::SetNumbers()\n";
m_a = ++s;
m_b = s;
ClassA::SetNumbers(s);
}
Any suggestions how to do it?...
Thank You in advance :)...
No. All parts of B (starting with A, as it's base) are constructed before B's constructor is called. So, by the time SetNumbers is called, no part of B (except for the A part) has been constructed --- and that may include the v-table, so there's no way to know where that call is going to go.
Of course, there is a simple solution to this: Call B::SetNumber() from within B's constructor (That is, after all, the purpose of B's constructor)
You can't do this for the simple logical reason that while the base class is being constructed, the derived class hasn't even begun to be constructed. You can't call a member function on an object that doesn't exist (yet).
In practice, even if you managed to call SetNumbers and assign to the member variables of the derived class before they were initialized they would surely be overwritten when they finally get initialized. I admit it's a bit pointless to reason about this as we would be well outside defined behaivour.
No, sorry. :( It might compile in one or two C++ compilers, but it's not recommended. From the C++ FAQ Lite section 10.7:
[10.7] Should you use the this pointer
in the constructor?
[...snip...]
Here is something that never works:
the {body} of a constructor (or a
function called from the constructor)
cannot get down to a derived class by
calling a virtual member function that
is overridden in the derived class. If
your goal was to get to the overridden
function in the derived class, you
won't get what you want. Note that you
won't get to the override in the
derived class independent of how you
call the virtual member function:
explicitly using the this pointer
(e.g., this->method()), implicitly
using the this pointer (e.g.,
method()), or even calling some other
function that calls the virtual member
function on your this object. The
bottom line is this: even if the
caller is constructing an object of a
derived class, during the constructor
of the base class, your object is not
yet of that derived class. You have
been warned.
NOTE: Emphasis mine.
More details at the link
The only time you can do this is when something is derived from a template that is parameterised by itself:
template<typename T> class base
{
T* down_cast() throw()
{
return static_cast<Derived*>(this);
}
const T* down_cast() const throw()
{
return static_cast<const Derived*>(this);
}
public:
base()
{
down_cast()->doSomething();
}
/* … */
};
class derived : private base<derived>
{
public:
void doSomething()
{
}
};
Note that doSomething is public and not virtual.
We can static_cast to derived, because it's known that derived is the derived type.
Deriving something from a base parameterised by itself is a strange thing to be doing at the best of times. It's said that when the ATL team in microsoft used it they asked the C++ compiler team if it was valid and nobody was sure, though it is valid because template construction depends on names as follows:
First the template is available, but not used in a class. Then, the name derived available. Then it instantiates the layout of base<derived> — this requires knowledge of the member variables and virtual functions, as long as none of that depends upon knowledge of derived’s layout (pointers and references are fine) this will all go okay. Then it will create the layout of derived, and finally it will create derived’s member functions, which may include creating member functions for base<derived>. So as long as base<derived> doesn’t contain a derived member variable (base classes can never contain a member variable of a type derived from themselves) or a virtual function that requires knowledge of derived’s layout we can indeed do the dicey-looking piece of inheritance above.
This includes being able to call non-virtual public members of derived from base during construction, because it's already part of base. There are strong limitations on this. In particular, if doSomething() depends on anything constructed in derived's constructor it won't work as derived hasn't been constructed yet.
Now, is this actually a good idea? No.
A simple design solution is to use aggregation instead of inheritance.
could anyone explain function overriding in c++ please! also am confused about virtual function concept. some tutorials say without the keyword virtual, both the derived class and base class objects invoke the base class function. then how does overriding take place?
There's no need to redocument what is already good and out there. I think this and this are a wonderful explanations about virtual functions. Then you probably also need to hear about abstract classes. Let us know if you have further questions.
Read this please. Concentrate on C++ sections. Then ask specific questions you have after reading.
Let me try to post an example (This is out of my head, so there may be slight syntax errors :) )
Baseclass:
class BaseClass
{
public:
void normalFunction();
virtual void virtualFunction();
}
Derived class:
class DerivedClass : public BaseClass
{
public:
void normalFunction();
virtual void virtualFunction();
}
Okay, so we got our classes defined. Now, some examples:
void main()
{
BaseClass base;
DerivedClass derived;
base.normalFunction(); //Invokes BaseClass::normalFunction();
base.virtualFunction(); //Invoked BaseClass::virtualFunction();
derived.normalFunction();//Invokes DerivedClass::normalFunction();
derived.virtualFunction();//Invokes DerivedClass::virtualFunction();
// Okay, nothing special yet, here comes the fun:
BaseClass *basePtr = &base;
BaseClass *derivedPtr = &derived;
basePtr->normalFunction(); //Invokes BaseClass::normalFunction();
basePtr->virtualFunction();//Invokes BaseClass::virtualFunction();
derivedPtr->normalFunction(); //Invokes BaseClass::normalFunction(); !! this is because it's a BaseClass pointer.
derivedPtr->virtualFunction();//Invokes DerivedClass::virtualFunction();
}
.. So, in conclusion, without virtual, the type of the pointer dictates which method will be invoked, with virtual, any type overriding the virtual method will have it's method called regardless of the pointer type :)
This is at a cose of a very minor overhead in the form of a vtable (virtual table), a compiler-detail which will map each method to the different derived types.
Each C++ class that has at least one virtual function contains a "virtual table" or VTABLE which is used to dynamically look up the address of a function at runtime.
Suppose you have two classes: Base and Derived. Further suppose that Derived derives from Base, and that "b" and "d" are instances of Derived, but b's compile-time type is Base and d's is Derived.
Now suppose that both Base and Derived declare a function "foo". Now, if "foo" is declared to be virtual in Base, then "foo" will have an entry in Base's VTABLE, and when you call "b.foo()" or "d.foo()", the compiler will know that it is a virtual function, and it will inject code that will look up the address of "foo" in the VTABLE at runtime.... which will find the address of the definition of "foo" as given in class Derived (i.e. Derived::foo).
Now suppose that both Base and Derived declare a function "foo", but "foo" has not been declared virtual in Base. When you call "b.foo()" or "d."foo()" the compiler will attempt to call Base::foo and Derived::foo directly, bypassing the virtual table lookup. Even though b's runtime type may be Derived, b's compile-time type is Base, and so calling "b.foo()" will result in "Base::foo" rather than "Derived::foo" being called.
In C++, the term "overriding" is used to refer to the former case; that is, when the function is declared as virtual, and another function in a derived class replaces the original function that was defined in the base class. By contrast, the term "overshadowing" is used to refer to the latter case; that is, a function in the derived class is called instead of the one in the base class, simply because it is closer in scope, but it has not truly replaced the function that was defined in the base class.
The override can only be done if you declare the function in the super virtual. Because it is virtual so it's not true ... meaning that is someone invoke it with that signature it may not invoke that function. We have to wait and see at runtime if someone overridden it. That is the meaning of virtual.
class A {
void F_A() { cout << "A' A"; }
virtual void F_B() { cout << "A' B"; }
}
class B : public A {
void F_B() { cout << "B' B"; }
}
A o = new B();
o.F_A(); // Non-virtual so the compiler knows that it can only be the one in class A
o.F_B(); // Virtual so the compiler does not know if at runtime ... o is instance of A or B. So it have to wait and see.
// In this case, it's B at runtime ('`new B()`'), so it run the one in B.
To sum up, if a function (method to be more precise) is declared 'virtual', it can be overridden. Otherwise, it can't be; hence, any invocation always goes to the one in the super class.
Hope this help clarifying.
For Virtual function always remember this thumb rule :
When function is normal then function
of type of object will be invoked,
When function is Virtual then function
of type of actual instance will be
called.
I like to illustrate this example with a Chess board;
class ChessPiece
{
public:
void moveTo(Pos dst);
virtual checkValidAndMoveTo(Pos dst) = 0;
};
class King: public ChessPieve
{ virtual checkValidAndMoveTo(Pos dst);}
class Queen: public ChessPieve
{ virtual checkValidAndMoveTo(Pos dst);}
// etc
ChessPiece* board[8][8];
So when a move is made to square the game will call checkValidAndMoveTo() on the piece.
board[pickedUpPiece.x][pickedUpPiece.y]->checkValidAndMoveTo()
This will now call the appropriate checkValidAndMoveTo() for the particular piece. Once this move is finished we expect it to call MoveTo(). Since at the point it knows what type is is it will drill to down and get the most overidden version of MoveTo() below it current type.