Почему нам на самом деле нужно Частное или Защищенное наследование в C++?

Неустранимая ошибка: Невозможно переопределить класс [имя класса]

Неустранимая ошибка: невозможно обновить [имя функции]

Это означает, что вы либо используете одно и то же имя функции / класса дважды, и вам нужно переименовать один из них, или это потому, что вы использовали require или include, где вы должны использовать require_once или include_once.

Когда класс или функция объявляется в PHP, он неизменен и не может быть позже объявлен с новым значением.

Рассмотрим следующий код:

class.php

<?php

class MyClass
{
    public function doSomething()
    {
        // do stuff here
    }
}

index.php

<?php

function do_stuff()
{
   require 'class.php';
   $obj = new MyClass;
   $obj->doSomething();
}

do_stuff();
do_stuff();

Второй вызов do_stuff() приведет к получению ошибка выше. Изменяя require на require_once, мы можем быть уверены, что файл, содержащий определение MyClass, будет загружен только один раз, и ошибка будет устранена.

58
задан user366312 11 December 2011 в 09:37
поделиться

7 ответов

Полезно, когда Вы хотите иметь доступ к некоторым членам базового класса, но не выставляя их в Вашем интерфейсе класса. Частное наследование может также рассматриваться как некоторый состав: C++, облегченный часто задаваемыми вопросами , дает следующий пример для иллюстрирования этого оператора

class Engine {
 public:
   Engine(int numCylinders);
   void start();                 // Starts this Engine
};

class Car {
  public:
    Car() : e_(8) { }             // Initializes this Car with 8 cylinders
    void start() { e_.start(); }  // Start this Car by starting its Engine
  private:
    Engine e_;                    // Car has-a Engine
};

Для получения семантического того же, Вы могли также записать автомобильный Класс следующим образом:

class Car : private Engine {    // Car has-a Engine
 public:
   Car() : Engine(8) { }         // Initializes this Car with 8 cylinders
   using Engine::start;          // Start this Car by starting its Engine
}; 

Однако этот способ сделать имеет несколько недостатков:

  • Ваше намерение намного менее ясно
  • , оно может привести к оскорбительному множественному наследованию
  • , оно повреждает инкапсуляцию класса Механизма, так как можно получить доступ к его защищенным участникам
  • , Вам разрешают переопределить Механизм виртуальные методы, который является чем-то, что Вы не хотите, если Вашей целью является простой состав
45
ответ дан Luc Touraille 24 November 2019 в 18:55
поделиться

Частный может быть полезным при довольно многих обстоятельствах. Только один из них является политиками:

частичная специализация шаблона класса ответ на эту проблему проектирования? .

Другой случай, где это полезно, состоит в том, чтобы запретить копирование и присвоение:

struct noncopyable {
    private:
    noncopyable(noncopyable const&);
    noncopyable & operator=(noncopyable const&);
};

class my_noncopyable_type : noncopyable {
    // ...
};

, поскольку мы не хотим это, у пользователя есть указатель типа noncopyable* к нашему объекту, мы происходим конфиденциально. Это рассчитывает не только для noncopyable, но и многих других таких классов также (политики, являющиеся наиболее распространенным).

40
ответ дан Community 24 November 2019 в 18:55
поделиться

Общедоступные модели IS-A наследования.
Непубличные модели IS-IMPLEMENTED-IN-TERMS-OF наследования.
модели Containment ИМЕЮТ - A, который эквивалентен IS-IMPLEMENTED-IN-TERMS-OF.

Sutter по теме . Он объясняет, когда Вы предпочли бы непубличное наследование включению для деталей реализации.

15
ответ дан Greg Rogers 24 November 2019 в 18:55
поделиться

Например, когда Вы хотите снова использовать реализацию, но не интерфейс класса И переопределить его виртуальные функции.

3
ответ дан Nemanja Trifunovic 24 November 2019 в 18:55
поделиться

Частное наследование главным образом используется по неправильной причине. Люди используют его для IS-IMPLEMENTED-IN-TERMS-OF, как обозначено в более раннем ответе, но по моему опыту это всегда более чисто, чтобы сохранить копию, а не наследоваться классу. Другой более ранний ответ, тот о CBigArray, обеспечивает идеальный пример этого антишаблона.

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

3
ответ дан 24 November 2019 в 18:55
поделиться

Я использовал и частное и защищенное наследование однажды или другой.

Частное наследование полезно, когда Вы хотите, чтобы что-то имело поведение базового класса и затем смогло переопределить ту функциональность, но Вы не хотите, чтобы целый мир знал о нем, и используете его. Можно все еще использовать интерфейс конфиденциально производный класс при наличии функционального возврата тот интерфейс. Также полезно, когда у Вас могут быть вещи, регистрируют себя для прислушиваний к обратным вызовам, как они могут зарегистрировать себя с помощью закрытого интерфейса.

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

0
ответ дан Daemin 24 November 2019 в 18:55
поделиться

Я когда-то реализовал эти структуры данных как классы:

  • Связанный список
  • Универсальный массив (краткий обзор)
  • Простой массив (наследовался универсальному массиву)
  • Большой массив (наследовался универсальному массиву)

интерфейс большого массива заставил бы его быть похожим на массив, однако, это был на самом деле связанный список простых массивов фиксированного размера. Таким образом, я объявил это как это:

template <typename T>
class CBigArray : public IArray, private CLnkList {
    // ...
-1
ответ дан pyon 24 November 2019 в 18:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: