2

In other words if I have a class

class A
{
public:
   A() { .. }
   virtual void somemethod() { .. }
};

is it ok to write

class B : public A
{
public:
   B() { .. }
protected:
   virtual void somemethod() { .. }
};

or are there some drawbacks with this approach?

iammilind
  • 68,093
  • 33
  • 169
  • 336
AndersK
  • 35,813
  • 6
  • 60
  • 86

4 Answers4

4

The main drawback with that approach is that one can always take a pointer/reference to A and invoke somemethod where is public. Why would you want to do such thing? If B is an A, and As have a public somemethod then so do Bs.

K-ballo
  • 80,396
  • 20
  • 159
  • 169
  • because if you have a class you may want to restrict the accessibility of certain methods. e.g. if you in the base class have method A(int),A(char),A(double) maybe you want to restrict in the derived class the usage of A say only allow A(char) – AndersK Sep 28 '11 at 19:35
  • the alternative is to throw an exception when used in the wrong context but i was thinking it may be better to restrict the usage of the method altogether instead. – AndersK Sep 28 '11 at 19:37
  • @Anders K.: It may be better to redesign you classes. Shouldn't the inheritance be private in that case? – K-ballo Sep 28 '11 at 19:48
  • 2
    @AndersK. ... but you will not restrict the use in the derived class, only when used as a derived. That is, as K-ballo points out, the user can just upcast and call the method on the base class, where it is public. That is, what you are doing is providing complex partial solution that will not solve your actual problem. – David Rodríguez - dribeas Sep 28 '11 at 20:02
  • 1
    And your actual problem is, "I would like to violate (a variant of) the LSP in cases where someone tries to substitute the type B in place of A in generic code. Please help me". To which the common response from experienced programmers is, "no!". – Steve Jessop Sep 29 '11 at 00:05
  • @David I agree, I think my main idea was just to indicate for the user of the derived class that some of the methods should not be used since that is anyway (it seems) the best you can do with this approach. You can circumvent most things but in doing so the user needs to do it deliberately and not by accident – AndersK Oct 03 '11 at 07:11
2

I would say this defeats the purpose of polymorphism, because when you write a function that accepts a polymorphic type, the derived type should work equally well with it:

void fun(A* a){
   a->somemethod();
}
...
A* a = new B();
fun(a); // Shouldn't this work?!
        // According to Liskov Principle, you are doing it wrong!
        // but really who cares, it depends on your justification
        // of a solution to the the problem at hand.

IMHO, it depends on the specific problem you are trying to solve because I don't believe in "always" successful "best practice".

Khaled Alshaya
  • 94,250
  • 39
  • 176
  • 234
0

There is no drawback with this approach. The only limitation is that B::somemethod() cannot be called with B object/pointer/reference. It can be now invoked only using A's pointer or reference.

In fact, I have seen that sometimes this limitation is introduced intentionally. Such scenarios are when the developer of class B wants to convey the message that, somemethod() is meant to be called only polymorphically using base class handle.

iammilind
  • 68,093
  • 33
  • 169
  • 336
0

No drawback.

But no real advantage to do this.
You still have accesses to somemethod() via a pointer to the case class.

So no drawback and no advantages on the technical side.
So now we move onto how easy it is to use you object. Here there is a downside as you are confusing the user of the object (why is it protected at this level but not the lower level)? So you are creating work for yourself in documenting why you made this decision and what you are trying to achieve by using this technique.

What is it that you really trying to achieve?

Martin York
  • 257,169
  • 86
  • 333
  • 562