Click to See Complete Forum and Search --> : Private Derivation


Bhadresh
July 2nd, 1999, 04:12 AM
Hi,
I have one query, can you please explain it to me..

Below is an example,
Here, In derive class, I am making virtual function Private which is Public in Base class.
I am calling that private function by base class pointer.

As the function is private in derive class, that function should not called from main(). But compiler doesn't give any error.
I know that compiler cannot detect these errors..

My question is,
Is this a correct behavior in terms of C++ ? Calling private function from outside ?
or
This is a fault but because of the limitation of compiler we cannot detect it ?
or
something else ?

Can you please write me ASAP.

#include "stdafx.h"
// some pure virtual (abstract) class
class Base
{
public:
virtual CallMe() = 0;
};


// Some derived class
class Derive1 : public Base
{
public:
CallMe(){ AfxMessageBox( " Derive1");}
};


// Some derived class
class Derive2 : public Base
{
private:
CallMe(){ AfxMessageBox( " Derive2");
};


void main()
{
Derive1 d1;
Derive2 d2;
Base* b;
d1.CallMe(); // NO ERROR
b = (Base*) &d2;
b->CallMe(); // A BIG FLAW I CAN CALL PRIVATE MEMBER OF Derive2
}





Bhadresh,
Mahindra-British telecom, Pune, India

Paul McKenzie
July 2nd, 1999, 04:54 AM
It is not a flaw. You are asking the compiler to determine which virtual function to call at compile time, which can't be done in C++. In C++, virtual functions implement *dynamic* binding. This means that at runtime the correct virtual function is resolved, not at compile time. Since the class Base CallMe() has public access, the compiler correctly determines that you can call it. It doesn't and cannot predict from Base::CallMe() which virtual function is being called until the program is actually running. By that time, it's too late to determine whether CallMe() is really public, private, or protected in the derived class.

However, if you called d2.CallMe(), the compiler knows right away that it can't be called since you are making a direct call to the d2 object and not through a virtual call.

Hope this explains things.

Regards,

Paul McKenzie

Bhadresh
July 2nd, 1999, 05:29 AM
Thanks for reply, I understand your meaning,

But don't you think compiler should give error message that "Virtual function which is public in base class cannot be private in derived class, It must be public in derived class" ?


Bhadresh,
Mahindra-British telecom, Pune, India

July 2nd, 1999, 06:41 AM
So finally in his program, which CallMe is being executed?.
The derived class CallMe?.

Paul McKenzie
July 2nd, 1999, 10:34 AM
It could definitely be a warning. I don't know if it could be an error because VC++ cannot give errors that are not considered errors by the C++ standard. Also, there could be reasons why you want to do what you did. Your code makes sure that you can only call the CallMe() function using a base pointer, and cannot call it through a derived class directly. A call to d2.CallMe() will give a syntax error.

Regards,

Paul McKenzie

July 2nd, 1999, 02:55 PM
There is no flaw at all.
Compiler does everything correctly, because an actual interface to
the object of your derived class is an abstract "Base" class.
In ADT class you declared virtual void CallMe() = 0 function as public,
that is it, the interface function is public, hence no matter what derived
class does it will ever be public.

Paul McKenzie
July 2nd, 1999, 06:19 PM
Let's also look at the opposite of your situation: How about a base class declaring a virtual function as protected, but the derived classes make them public. The CDialog class is an example of this. The CDialog class declares the constuctor CDialog() as protected. The derived classes then declare their constructor as public. The reason for this is that this prevents the program from creating a CDialog explicitly. The only way to create a CDialog is to invoke the constructor of a class derived from CDialog.

So the quick answer is that you are allowed to change access specifiers in derived classes without a warning or error.

Regards,

Paul McKenzie