Есть ли примеры, когда нам * нужно * защищенное наследование в C ++? - PullRequest
14 голосов
/ 28 августа 2008

Хотя я видел редкие случаи, когда требовалось личное наследование, я никогда не сталкивался со случаем, когда защищенное наследование необходимо. У кого-нибудь есть пример?

Ответы [ 3 ]

13 голосов
/ 28 августа 2008

Люди здесь, кажется, ошибаются Наследование защищенного класса и Защищенные методы.

FWIW, я никогда не видел, чтобы кто-нибудь использовал защищенное наследование классов, и если я правильно помню, я думаю, что Страуструп даже считал «защищенный» уровень ошибкой в ​​c ++. Там очень мало, что вы не можете сделать, если вы удалите этот уровень защиты и полагаться только на публичных и частных.

5 голосов
/ 11 ноября 2008

Существует очень редкий случай использования защищенного наследования. Здесь вы хотите использовать ковариация :

struct base { 
    virtual ~base() {} 
    virtual base & getBase() = 0;
}; 

struct d1 : private /* protected */ base { 
    virtual base & getBase() { 
        return this; 
    } 
}; 

struct d2 : private /* protected */ d1 {
    virtual d1 & getBase () { 
        return this; 
    } 
}; 

Предыдущий фрагмент кода пытался скрыть свой базовый класс и обеспечивать контролируемую видимость баз и их функций по любой причине, предоставляя функцию "getBase".

Однако в структуре d2 произойдет сбой, поскольку d2 не знает, что d1 является производным от base. Таким образом, covariance не будет работать. Выходом из этого является получение их защищенными, так что наследование видно в d2.

Подобный пример использования этого - когда вы наследуете std::ostream, но не хотите, чтобы случайные люди писали в ваш поток. Вы можете предоставить виртуальную getStream функцию, которая возвращает std::ostream&. Эта функция может подготовить поток к следующей операции. Например, установка определенных манипуляторов.

std::ostream& d2::getStream() {
    this->width(10);
    return *this;
}

logger.getStream() << "we are padded";
1 голос
/ 17 сентября 2008

C ++ FAQ Lite упоминает случай, когда использование частного наследования является законным решением (см. [24.3.] Что мне следует предпочесть: композиционное или частное наследование? ). Это когда вы хотите вызвать производный класс из частного базового класса через виртуальную функцию (в данном случае derivedFunction()):

class SomeImplementationClass
{
protected:
    void service() {
        derivedFunction();
    }

    virtual void derivedFunction() = 0;      

    // virtual destructor etc
};

class Derived : private SomeImplementationClass
{
    void someFunction() {
        service();
    }

    virtual void derivedFunction() {
        // ...
    }

    // ...
};

Теперь, если вы хотите наследовать от класса Derived и хотите использовать Base::service() из производного класса (скажем, вы хотите переместить Derived::someFunction() в производный класс), самый простой способ сделать это - изменить частное наследование Base на защищенное наследование.

Извините, не могу придумать более конкретный пример. Лично я хотел бы сделать все наследство публичным, чтобы не тратить время на обсуждение «должен ли я сделать отношения наследования защищенными или частными».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...