I am confused regarding checking of access specifiers statically or dynamically. It is said that access specifiers are not checked dynamically. What does that mean ?
This example has been taken from different posts on SO. Consider this example
Example A:
class Base
{
public:
virtual void Message() = 0;
};
class Intermediate : public Base
{
//Is Message method virtual here too ? is it private or public ?
};
class Final : public Intermediate {
void Message() {
cout << "Hello World!" << endl;
}
};
Final final;
Now suppose I do something like this
Final* finalPtr = &final;
finalPtr->Message();
The above wont work and my understanding is that in Final class the Message Method is private. Is that correct ? If so why does this work ? the method in
Intermediate* finalPtr = &final; // or Base* finalPtr = &final;
finalPtr->Message();
Is the reason why the above code is working because the base class pointer is instantiated with a derived class. If so why does the call to Message() work. The post on SO states that since the inheritance is public hence it will be inherited as public function ? on the other hand the function itself in the class has the private access specifier (since by default its private in a class). I am confused here and I would appreciate if someone could clarify this. Would it be correct to say that if a base class is instantiated with a derived class. Then the access specifier of the base class method takes precedence over the access specifier of the derived class ?
Update :
Also I noticed that if I change the Intermediate
and Final
code to the following
class Intermediate : public Base
{
public: //Incase this public was absent then the following example wont work
void Message() {
cout << "Hello World! Intermediate" << endl;
}
};
class Final : public Intermediate {
void Message() {
cout << "Hello World! final" << endl;
}
};
and use it as such
Intermediate* i = new Final();
i->Message();
Then inorder to get the output "Hello World! final"
it is necessary to mark the interface method as public. Why is that ? The method Message
was inherited as public . Why do i need to mark it as public now ?
The statement in your quote means that the access check is based on the static type of the expression you have applied the .
operator to (or ->
which is equivalent to *
with .
).
If T
is a type then for:
T *t = something....;
t->foo();
the the access check is for the name T::foo
, even if the pointer actually points to an object of a class derived from foo
.
Another way of saying this is that the access check must be able to be performed at compile-time. There is no such thing as a "run-time accessability failure".
In your code example you have:
Intermediate* finalPtr = something.....;
finalPtr->Message();
The name being looked up is Intermediate::Message
. The class Intermediate
has Message
as a public
function, so this check succeeds.
Your comment suggests maybe you are unsure about the accessability of inherited functions. There are three types of derivation (somewhat confusingly, they are also called private
, protected
, public
). public
inheritance is the most common; it means that public
members of the base class are also public
members of the derived class.
Since Base::Message
is public, and Intermediate
is publicly derived from Base
, then Intermediate::Message
is also public.
To be clear, it is names which have access rights. Base::Message
and Intermediate::Message
are two different names, but they both name the same function.
In Final
, it declares the name Message
in its private
section, this means that Final::Message
is private. Even though the inheritance was public, the new declaration of a name Final::Message
shadows the one inherited from the Base.
To answer the "update". When the code is:
class Intermediate : public Base
{
public: //Incase this public was absent then the following example wont work
void Message() {
cout << "Hello World! Intermediate" << endl;
}
};
you have declared Intermediate::Message
as public. Therefore you can call the function through a pointer of type Intermediate *
. That's what "public" means. If you make it private
then you cannot call it.
I don't know quite what you mean by "The method Message was inherited as public . Why do i need to mark it as public now". When you wrote void Message ()
inside class Intermediate
it declares a new function. That function's name shadows the inherited name.
This checking is done at compile time only.
You have made Message () public in final so it can be called from final.
The Intermediate class has no knowledge of how Message is defined in the Final class.
To make Matt McNabb's answer shorter. if you don't specify the function's access it's private. Like Final::Message
it is possible for a derived class to lower the accessibility of the parent class. This is useful in some cases (like blocking default/copy constructors, etc)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With