7

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 ?

Community
  • 1
  • 1
Rajeshwar
  • 11,179
  • 26
  • 86
  • 158
  • 1
    You should have linked the other posts. Because you didn't, you will get the exact same explanation you don't understand. – Ben Voigt Sep 20 '14 at 04:36

3 Answers3

8

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.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Then 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 ? – Rajeshwar Sep 22 '14 at 04:20
  • There is no such thing as "base class is instantiated with a derived class", so that would not be correct. – M.M Sep 22 '14 at 04:20
  • 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". This means that incase i did not specify the `public:` access specifier the updated example would not have worked and I would have gotten a "cannot access method Message" – Rajeshwar Sep 22 '14 at 04:45
  • @Rajeshwar In a `class` the default access is `private:` (i.e. the accessability of names you declare before you wrote `public:`, `protected:`, or `private:`) – M.M Sep 22 '14 at 04:46
  • I understand that. After going through your answer its starting to make sense. I am still in the process of absorbing this information – Rajeshwar Sep 22 '14 at 04:47
  • @Rajeshwar it sounds like you are unsure about how access works, maybe do some examples that don't involve pointers or references (just `Base b; Intermediate i; Final f;`) until you are sure you understand that – M.M Sep 22 '14 at 04:49
4

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.

user3344003
  • 20,574
  • 3
  • 26
  • 62
  • Then will this be correct ? 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 ? – Rajeshwar Sep 20 '14 at 04:51
  • @Rajeshwar If you have a pointer to the base class, you can only use the base class interface, the compiler has no knowledge of what that pointer actually points to. – molbdnilo Sep 20 '14 at 07:14
  • What? He made Message() private in class Final, so it can not be called via a reference/pointer to Final. This is checked (statically) at compile time though, so even if at runtime the (dynamic) type of the object is Final, the function remains accessible. – Ulrich Eckhardt Sep 20 '14 at 07:55
1

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)

aivision2020
  • 619
  • 6
  • 14