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.
Related
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.
Suppose we have two classes, one derived from other and it contains only one virtual non-pure method like this:
class Base
{
public:
virtual void method()
{
cout << "method() called from Base" << endl;
}
};
class Derived : public Base
{
public:
void method()
{
cout << "method() called from Derived" << endl;
}
};
int main()
{
Base *instance1 = new Derived();
instance1->method();
Derived derived;
derived.method();
}
Why, if we do not specify explicitly "public" access modifier in Derived class (so, compiler assumes that it's private) it wouldn't compile? Why instantiation way(via pointer and via regular variable) does affect to the visibility scope? Is there any rationale regarding this behavior?
Many thanks!
If you don't write public: then it's as if you've written private:. If you're asking why the language doesn't automatically switch to public: for Derived::method() (because it overrides Base::method() which is already public)… well, it could! This would be possible.
However, it would also be extremely confusing and misleading when reading the code. As a programmer I much prefer that my class definition isn't fundamentally altered behind my back like that.
The compiler throws out an error (as you've discovered) allowing me to make the change myself as I deem appropriate (whether that's making Derived::method() public, or Base::method() private!), which in my opinion is by far the best outcome.
If instead you're asking why a difference in visibility even matters at all, then that seems fairly obvious, does it not? If the user were calling a function through the Base class interface, in which method() is public, and this ended up automatically invoking a private function in a derived class, that violates the contract of the derived class. And because it's only the names that are protected by these visibility rules, the language adds an extra check for overridden methods to extend that protection as much as possible in the case of virtual function dispatch.
Something very similar is given as an example in the standard where the rules for these things are specified [class.access.virt]:
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.
[ Example:
class B {
public: virtual int f();
};
class D : public B
{
private: int f();
};
void f()
{
D d;
B* pb = &d;
D* pd = &d;
pb->f(); // OK: B::f() is public, // D::f() is invoked
pd->f(); // error: D::f() is private
}
— end example ]
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.
The above answer both your questions:
Why does it not compile - as per rule 2 above access is checked using the type of the expression (i.e. the static not dynamic type)
What is the rationale - again as described above it is generally not known what the dynamic type is. To demonstrate, consider this: You can link new derived classes to an existing code defining a base class without recompiling this code: then clearly it would have no chance of determining the access controls of the derived (which didn't even exist when it was compiled).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++: overriding public\private inheritance
class base {
public:
virtual void doSomething() = 0;
};
class derived : public base {
private: // <-- Note this is private
virtual void doSomething()
{ cout << "Derived fn" << endl; }
};
Now if I do the following:
base *b = new derived;
b->doSomething(); // Calls the derived class function even though that is private
Question:
It's able to call the derived class function even though it is private. How is this possible?
Now if I change the inheritance access specifier from public to protected/private, I get a compilation error:
'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible
Note: I am aware of the concepts of the inheritance access specifiers. So in the second case as it's derived private/protected, it's inaccessible. But I wonder about the answer to first question. Any input will be highly appreciated.
Access control is implemented at compile time, not run-time, while polymorphism (including the use of virtual functions) is a run-time feature.
In the first case the access check is done (as it is always done) on the static type that the call is made through. The static type of *b is base, and in that case doSomething() is public.
C++03 11.6 "Access to virtual functions" says:
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. [Example:
class B {
public:
virtual int f();
};
class D : public B {
private:
int f();
};
void f()
{
D d;
B* pb = &d;
D* pd = &d;
pb->f(); //OK:B::f()is public,
// D::f() is invoked
pd->f(); //error:D::f()is private
}
—end example]
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.
Keep in mind especially that "the access of the member function in the class in which it was defined (D in the example above) is in general not known". In general, at the point in your example where b->doSomething(); is called, the compiler may have no knowledge at all about derived (or child), much less whether or not the access to derived::doSomething() is private.
Private functions are meant to be hidden from the outside world and from the derived classes. Although you are overriding the access specifier of the parent's DoSomething and making it private, you are instantiating a base class; so in the first case, you can call base's DoSomething as it is public. This scenario can be used if you want to stop people deriving from your derived class.
In the second case, the private access specifier causes the base's members not to be exposed to the users of the derived class, which effectively makes the derived class useless.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++: overriding public\private inheritance
class base {
public:
virtual void doSomething() = 0;
};
class derived : public base {
private: // <-- Note this is private
virtual void doSomething()
{ cout << "Derived fn" << endl; }
};
Now if I do the following:
base *b = new derived;
b->doSomething(); // Calls the derived class function even though that is private
Question:
It's able to call the derived class function even though it is private. How is this possible?
Now if I change the inheritance access specifier from public to protected/private, I get a compilation error:
'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible
Note: I am aware of the concepts of the inheritance access specifiers. So in the second case as it's derived private/protected, it's inaccessible. But I wonder about the answer to first question. Any input will be highly appreciated.
Access control is implemented at compile time, not run-time, while polymorphism (including the use of virtual functions) is a run-time feature.
In the first case the access check is done (as it is always done) on the static type that the call is made through. The static type of *b is base, and in that case doSomething() is public.
C++03 11.6 "Access to virtual functions" says:
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. [Example:
class B {
public:
virtual int f();
};
class D : public B {
private:
int f();
};
void f()
{
D d;
B* pb = &d;
D* pd = &d;
pb->f(); //OK:B::f()is public,
// D::f() is invoked
pd->f(); //error:D::f()is private
}
—end example]
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.
Keep in mind especially that "the access of the member function in the class in which it was defined (D in the example above) is in general not known". In general, at the point in your example where b->doSomething(); is called, the compiler may have no knowledge at all about derived (or child), much less whether or not the access to derived::doSomething() is private.
Private functions are meant to be hidden from the outside world and from the derived classes. Although you are overriding the access specifier of the parent's DoSomething and making it private, you are instantiating a base class; so in the first case, you can call base's DoSomething as it is public. This scenario can be used if you want to stop people deriving from your derived class.
In the second case, the private access specifier causes the base's members not to be exposed to the users of the derived class, which effectively makes the derived class useless.
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.