Overriding methods with lower permission

D

danil52

Hello there,
I have the following code:

class Base {
public:
virtual void f() {cout << "Base::f()" << endl;}
virtual void f(int) {cout << "Base::f(int)" << endl;}
};


class Derived : public Base {
void f() {cout << "Derived::f()" << endl;}
};

int main() {
Base *ptr = new Derived();
ptr->f();
ptr->f(1);

return 0;
}

As you can see, I overridden Base::f() from public, to private access
permission. Being the Java guy that I am, I expected a compiler error.
But to my surprise, the program ran fine, and called the private
version? Is this a compiler bug (I use g++), or is the function
explicitly converted to public? Thank you.
 
P

puzzlecracker

Hello there,
I have the following code:

class Base {
public:
  virtual void f() {cout << "Base::f()" << endl;}
  virtual void f(int) {cout << "Base::f(int)" << endl;}

};

class Derived : public Base {
  void f() {cout << "Derived::f()" << endl;}

};

int main() {
  Base *ptr = new Derived();
  ptr->f();
  ptr->f(1);

  return 0;

}

As you can see, I overridden Base::f() from public, to private access
permission. Being the Java guy that I am, I expected a compiler error.
But to my surprise, the program ran fine, and called the private
version? Is this a compiler bug (I use g++), or is the function
explicitly converted to public? Thank you.

That's allowed in C++. However, you're not allowed to provide more
accessibility than provided by super class, in other words making it a
private member a public in subclass is prohibited under the current
standard.
 
D

danil52

Java creates many misapprehensions.


Neither. Base::f is public, and Derived::f is private, just like you
said they should be. Access is checked statically. That is, ptr->f()
can call f because f is public in Base. Try it with a pointer to
Derived.

--
  Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Well, that's obvious, access is checked only at compile-time. Compiler
would have no idea which object is being used at run-time. Using
pointer to Derived would produce an error - as expected. I understand
all of that.

But the fact is - I am able to call a private function! Compiler lets
me override the function and give it lower permissions, which,
logically shouldn't happen (Java compiler would choke on that piece of
code).
 
M

Marcel Müller

Hi,

Well, that's obvious, access is checked only at compile-time. Compiler
would have no idea which object is being used at run-time. Using
pointer to Derived would produce an error - as expected. I understand
all of that.

But the fact is - I am able to call a private function! Compiler lets
me override the function and give it lower permissions, which,
logically shouldn't happen (Java compiler would choke on that piece of
code).

it is quite common that an implementation of an interface (in fact a
pure function) should not be called directly. The standard gives you a
chance to restrict this.


Marcel
 
G

Gennaro Prota

Pete said:
class Base
{
void f();
public:
void g();
};

class Derived: public Base
{
void f(int); // hides Base::f
void g(int); // hides Base::g
// make base version visible (ignore duplication):
using Base::f; // OK: same access
using Base::g; // OK: more restricted access
protected:
using Base::f; // error: less restricted access
using Base::g; // OK: more restricted access
public:
using Base::f; // error: less restricted access
using Base::g; // OK: same access
};

Where did you get this from? First, f isn't accessible in Derived, and
that's an error. All the rest is OK; aren't using declarations (and
not "directives") intended to allow what was previously made with
access declarations?
 
J

James Kanze

I have the following code:
class Base {
public:
virtual void f() {cout << "Base::f()" << endl;}
virtual void f(int) {cout << "Base::f(int)" << endl;}
};
class Derived : public Base {
void f() {cout << "Derived::f()" << endl;}
};
int main() {
Base *ptr = new Derived();
ptr->f();
ptr->f(1);
return 0;
}
As you can see, I overridden Base::f() from public, to private
access permission. Being the Java guy that I am, I expected a
compiler error.

Are you sure? I always thought that in Java, private meant
private; that since Derived::f() was private, it had nothing to
do with Base::f() (except, of course, that its presence would
prevent you from overriding Base::f()). (But I'm far from
sure.)
But to my surprise, the program ran fine, and called the
private version? Is this a compiler bug (I use g++), or is the
function explicitly converted to public?

Not exactly. You're calling Base::f(), which is public. It's
not considered relevant to access control that the function
which actually gets executed is Derived::f(). (It can't be
since access control is fully resolved at compile time, and the
compiler can't know which function will actually get executed.)
In other words, access control is always applied to the static
type.

In general, it's probably not a good idea to tighten access
controls in the derived class, because it's confusing; client
code can still call the function through an interface to the
base. On the other hand, in certain rare cases, the opposite
might be appropriate: overriding a private virtual function with
a public function in the derived class.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top