0

As in Private function member called outside of class, one can write the following code:

#include <iostream>

class A {
public:
  virtual void f() { std::cout << "A::f()"; }
};

class B : public A {
private:
  void f() override { std::cout << "B::f()"; }
};

void g(A &g) { g.f(); }

int main() {
  A a;
  g(a);
  a.f();
  B b;
  g(b);
  b.f(); // compilation failure
}

Of course, the compiler refuses to compile the last line, because the static analysis of the code reveals that B::f() is defined but private.

What seriously troubles me is the relation with the conceptual generalization/specialization. It is generally considered that you must be able to manipulate an instance of a subtype at least the same way you manipulate an instance of the super type.

This is the basis of the Liskov's substitution principle. In the given example, that is respected when g() is called either with an argument of type A or one of type B. But the last line is not accepted, and it seems that in such a case the substitution principle is violated in some way (consider a call-by-name as in a macro-definition #define h(x) (x.f())).

Even if one may consider that the Liskov's principle is not violated (macros are not real part of the language, so ok), the fact that the last line gives a compile-time error, at least means that objects of type B can't be manipulated as A's can be. So that B is not a specialization of A even if the derivation is public.

Thus in C++, using a public derivation does not guarantee that you are effectively implementing a specialization. You need to consider more properties of the code to be sure that you have a ‘‘correct’’ specialization.

Am I wrong ? Is someone able to give me a justification for it ? I would like a good semantic argument, I mean at least something much more elaborate than Stroustrup's ones like ‘‘C++ tries not to constrains you, you are free to use it if you want and not if you don't want’’. I think that a language need to be founded on a reasonable model, not on a huge list of possible tricks.

Maxpm
  • 24,113
  • 33
  • 111
  • 170
Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
  • I don't understand how you can override a public virtual method with a private one. – Matthew Jan 22 '15 at 21:43
  • 1
    This is possible in C++, so the question is not ‘‘how?’’ but why is this possible? – Jean-Baptiste Yunès Jan 22 '15 at 21:47
  • I'm fairly certain that, according to the C++ standard, accessibility is simply not part of a member function signature. That's answers as to why this is allowed. I'm not sure I can answer whether the standard *should* allow it, though. – mbgda Jan 22 '15 at 22:16
  • Ok but this is a technical argument. But I want to know why, because it is very weird... – Jean-Baptiste Yunès Jan 22 '15 at 22:17
  • I just explained why. Overriding works by signature and accessibility doesn't change the function signature. – mbgda Jan 22 '15 at 22:18
  • No, you explained how it works (I know how), not why is this possible ? Why C++ designers allowed it as it is mostly a non-sense (to me) ? It is strictly forbidden in every other OOP language I know. – Jean-Baptiste Yunès Jan 22 '15 at 22:24
  • 1
    I'm not sure why it was designed this way. It's worth noting that it's kind of misleading to call C++ an OOP language. It's a multi-paradigm language so it's not 100% designed under the OOP paradigm. Also, I suppose I can think of one use case for it. You want to provide an implementation of 'f' inside of 'B' but you don't want anyone who knows they have a 'B' to directly call it. You want to force them to always call it via the base class handle, for whatever reason. Obviously, using NVI would be a better way to approach this. – mbgda Jan 22 '15 at 22:53
  • Ok, you mean by the use of a factory, but if you don't want others to know that `B` exists, then there is no need to protect anything in it. – Jean-Baptiste Yunès Jan 23 '15 at 06:11
  • Yeah, it's not a great example. Maybe we need to get Stroustrup on here to answer for this :) – mbgda Jan 23 '15 at 13:41

0 Answers0