Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need to understand the statement "Accessability is checked statically and not dynamically in C++"

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 ?

like image 433
Rajeshwar Avatar asked Sep 20 '14 03:09

Rajeshwar


3 Answers

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.

like image 65
M.M Avatar answered Oct 22 '22 07:10

M.M


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.

like image 42
user3344003 Avatar answered Oct 22 '22 08:10

user3344003


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)

like image 20
aivision2020 Avatar answered Oct 22 '22 08:10

aivision2020