I came across a question while taking iKM test. There was a base class with two abstract methods with private access specifier. There was a derived class which was overridin
Yes, this is legal, accessibility 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 would you want to do that? It only matters if you use the derived class B directly (2nd param of f()) as opposed to through the base A interface (1st param of f()).
If you always use the abstract A interface (as I would recommend in general), it still complies to the "IS-A" relashionship.
Yes, this is allowed as long as the signature is the same. And in my opinion, yes, you're right, overriding visibility (for example, public -> private) breaks IS-A. I believe Scott Myers Effective C++ series has a discussion on this one.
As many of the guys pointed out it is legal.
However, "IS-A" part is not that simple. When it comes to "dynamic polymorphism" "IS-A" relation holds, I.e. everything you can do with Super you can also do with Derived instance.
However, in C++ we also have something that is often referred as static polymorphism (templates, 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 seems to be ok:
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 "IS-A" relation 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 visibility for method is "rather legal" but that's one of the ugly things in C++ that may lead you to pitfall.
It is allowed, in both directions (ie, from private to public AND from public to private).
On the other hand, I would argue it does not break the IS-A relationship. I base my argument on 2 facts:
Base& (or Base*) handle, you have exactly the same interface as beforepublic and calling the private method directly anyway: same effect with more typing