Calling private function by upcasting [duplicate] - c++

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.

Related

Calling Derived class method which is private from Base class pointer [duplicate]

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.

Access of member functions in C++ inheritance

I am just confused about the tiny program on inheritance below:
#include<iostream>
using namespace std;
struct B {
virtual int f() { return 1; }
}; // f is public in B
class D : public B {
int f() { return 2; }
}; // f is private in D
int main()
{
D d;
B& b = d;
cout<<b.f()<<endl; // OK: B::f() is public, D::f() is invoked even though it's private
cout<<d.f()<<endl; // error: D::f() is private
}
I can't figure out why D::f() is private, D is public inherited from B, so the public function f in B
is also public in D (I know without inheritance, member access is private by default)
f is a virtual function in B, so if we call b.f(), we actually call D::f(), but just as the illustration mentioned, why D::f() is able to be invoked even though it's private?
Can anyone explain the simple inheritance problem in detail?
This has to do that with virtual dispatch is a runtime concept. The class B doesn't care which class extends it, and it doesn't care if it's private or public because it can't know.
I can't figure out why D::f() is private, D is public inherited from B, so the public function f in B
is also public in D(I know without inheritance, member access is private by default)
D::f() is private because you made it private. This rule isn't affect by inheritance nor virtual dispatch.
f is a virtual function in B, so if we call b.f(), we actually call D::f(), but just as the illustration mentioned, why D::f() is able to be invoked even though it's private?
Because in reality, when invoking b.f(), the compiler has no idea which function will actually be called. It will simply call the function f(), and since B::f is virtual, the called function will be chosen at runtime. The runtime program has no information about which function is private or protected. It only know functions.
If the function is chosen at runtime, the compiler can't know at compile-time what function will be called, and the access specifier can't be known. In fact, the compiler won't even try to check if the function called will be private or not. The access specifier could be in some code that the compiler haven't seen yet.
As you've experienced, you can't call D::f directly. This is exactly what private will do: prohibit direct access of the member. You can, however, access it indirectly through a pointer or a reference. The virtual dispatch you use will do that internally.
Access specifiers apply to the function name only, they aren't some restriction on how or when the function can be called by other means. A private function could be called outside the class if it is made available by some means other than its name (for example, a function pointer).
For a class declared with class keyword, the default access-specifier is private. Your code is the same as:
// ...
class D: public B
{
private:
int f() { return 2; }
};
As you can see, f is private in D. It makes no difference what the access specifier was of any function in B with the same name. Be clear in your mind that B::f() and D::f() are two different functions.
The effect of the virtual keyword is that if f() without a scope qualifier is called on a B reference that refers to a D object, then even though it resolves to B::f(), actually D::f() is invoked instead.
This process still uses the access specifier for B::f(): access is checked at compile-time; but it might be run-time matter as to which function is called.
The C++ Standard has an exact example of this:
11.5 Access to virtual functions [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]
Can't explain it any clearer.
The answer given illustrates what is being done, but why would you ever want to do this, where the base class calls private virtual functions?
Well, there is a design pattern called the template method pattern that uses this technique of having a base class that calls private virtual functions in the derived class.
struct B
{
virtual ~B() {};
int do_some_algorithm()
{
do_step_1();
do_step_2();
do_step_3();
}
private:
virtual void do_step_1() {}
virtual void do_step_2() {}
virtual void do_step_3() {}
};
class D : public B
{
void do_step_1()
{
// custom implementation
}
void do_step_2()
{
// custom implementation
}
void do_step_3()
{
// custom implementation
}
};
int main()
{
D dInstance;
B * pB = &dInstance;
pB->do_some_algorithm();
}
This allows us to not expose the custom steps of class D to the public interface, but at the same time allows B to call these functions using a public function.
This actually has less to do with virtual dispatch and more to do with what access specifiers mean.
The function itself is not private; its name is.
Consequently, the function cannot be named outside of the scope of the class, e.g. from main. However, you can still do so through a name that is public (i.e. the base's virtual function that is overridden) or from a scope in which the function's name is accessible despite the private qualifier (e.g. a member function of that class).
That's just how it works.
why D::f() is able to be invoked even though it's private?
To understand virtual function mechanism it is good to know, how it is usually implemented. A function at runtime is actually no more than an address in memory where the executable code of the function body locates. To call the function we need to know its address (a pointer). C++ object with virtual functions representation in memory contains so called vtable - an array of pointers to the virtual functions.
Key point is that in derived classes vtable repeats (and may extend) the vtable of base class, but if the virtual function is overriden its pointer is replaced in derived object's vtable.
When a virtual function call is done through the base class pointer, the address of the virtual function is calculated as an offset in the vtable array. No other checks are done, just the function address is taken.
If it is a base class object, it will be the address of the base class function. If it is a derived class object, it will be the address of the derived class function, does not matter if it was declared private or not.
This how it works.
Member of struct is default to be public, and member of class is default to be private.
So f() in B is public and when it's derived to D, because you didn't explicitly declare it is public, so according to rules of derivation, it became private.

Requiring "public" access modifier when using instance in auto scope

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).

Derived class Private method is getting called

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.

Private virtual function in derived class [duplicate]

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.