Считается ли хорошей практикой изменение уровня защиты метода? - PullRequest
2 голосов
/ 28 сентября 2011

Другими словами, если у меня есть класс

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

, можно ли писать

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

или у этого подхода есть некоторые недостатки?

Ответы [ 4 ]

4 голосов
/ 28 сентября 2011

Основным недостатком этого подхода является то, что всегда можно взять указатель / ссылку на A и вызвать somemethod где public. Почему вы хотите сделать такую ​​вещь? Если B является A, а A s имеет public somemethod, то так же поступают B s.

2 голосов
/ 28 сентября 2011

Я бы сказал, что это противоречит цели полиморфизма, потому что когда вы пишете функцию, которая принимает полиморфный тип, производный тип должен одинаково хорошо с ним работать:

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.

ИМХО, это зависит отконкретную проблему, которую вы пытаетесь решить, потому что я не верю в «всегда» успешную «лучшую практику».

0 голосов
/ 28 сентября 2011

Нет недостатка.

Но нет никакого реального преимущества для этого.
У вас все еще есть доступ к somemethod() через указатель на класс дела.

Так что нет недостатка и нетпреимущества с технической стороны.
Итак, теперь мы переходим к тому, насколько легко использовать ваш объект.Здесь есть обратная сторона, поскольку вы путаете пользователя с объектом (почему он защищен на этом уровне, а не на нижнем уровне)?Итак, вы создаете работу для себя, документируя, почему вы приняли это решение и чего вы пытаетесь достичь с помощью этой техники.

Чего вы действительно пытаетесь достичь?

0 голосов
/ 28 сентября 2011

У этого подхода нет недостатка . Единственное ограничение заключается в том, что B::somemethod() нельзя вызывать с B объектом / указателем / ссылкой. Теперь он может быть вызван только с помощью указателя или ссылки A.

На самом деле, я видел, что иногда это ограничение вводится намеренно. Такие сценарии возникают, когда разработчик class B хочет передать сообщение о том, что somemethod() должен называться только полиморфно с использованием дескриптора базового класса.

...