Overriding with C ++ Different Access Specification

I came across a question while taking an iKM test. There was a base class with two abstract methods with a private access specifier. There was a derived class that redefined these abstract methods, but with a secure / public access specifier.

I have never encountered a situation where overridden methods in a derived class have different access specifications. It is allowed? If so, does it correspond to β€œIS A” between the base and the derivative (that is, safely replaceable).

Could you give me some links that can provide more detailed information about such class activities?

Thanks.

+7
source share
4 answers

As many of the guys said this is legal.

However, the IS-A part is not so simple. When it comes to "dynamic polymorphism", the relationship is "IS-A", Ie everything you can do with Super, you can also do with an instance of Derived.

However, in C ++, we also have what is often referred to as static polymorphism (patterns, most of the time). Consider the following example:

class A { public: virtual int m() { return 1; } }; class B : public A { private: virtual int m() { return 2; } }; template<typename T> int fun(T* obj) { return obj->m(); } 

Now, when you try to use "dynamic polymorphism", everything looks fine:

 A* a = new A(); B* b = new B(); // dynamic polymorphism std::cout << a->m(); // ok std::cout << dynamic_cast<A*>(b)->m(); // ok - B instance conforms A interface // std::cout << b->m(); fails to compile due to overriden visibility - expected since technically does not violate IS-A relationship 

... but when you use "static polymorphism", you can say that the "IS-A" relationship no longer holds:

 A* a = new A(); B* b = new B(); // static polymorphism std::cout << fun(a); // ok //std::cout << fun(b); // fails to compile - B instance does not conform A interface at compile time 

So, in the end, changing the visibility for a method is β€œpretty legitimate,” but it's one of the ugly things in C ++ that can lead to errors.

+1
source

Allowed in both directions (i.e. from private to public AND from public to private ).

On the other hand, I would say that this does not violate the IS-A relationship. I base my argument on two facts:

  • using the Base& (or Base* ) descriptor, you have the same interface as before
  • you could (if you want) introduce the forward public method and call the private method directly: the same effect with more typing
+2
source

Yes, this is legal; availability is checked statically (not dynamically):

 class A { public: virtual void foo() = 0; private: virtual void bar() = 0; }; class B : public A { private: virtual void foo() {} // public in base, private in derived public: virtual void bar() {} // private in base, public in derived }; void f(A& a, B& b) { a.foo(); // ok b.foo(); // error: B::foo is private a.bar(); // error: A::bar is private b.bar(); // ok (B::bar is public, even though A::bar is private) } int main() { B b; f(b, b); } 

Now, why do you want to do this? This only matters if you directly use the derived class B (second parameter f() ), and not through the base interface A (1st pair f() ). If you always use the abstract A interface (as I would recommend in general), it still corresponds to the "IS-A" mode.

+2
source

Yes, this is allowed as long as the signature is the same. And, in my opinion, yes, you are right, redefinition of visibility (for example, public β†’ private) interrupts IS-A. I believe that Scott Myers "Effective C ++ Series" has a discussion on this.

+1
source

All Articles