использовать Mixins для ES6 multiple Inheritance.
let classTwo = Base => class extends Base{
// ClassTwo Code
};
class Example extends classTwo(ClassOne) {
constructor() {
}
}
Отметьте после принятия ответа: Это не полный ответ. Прочитайте другие ответы как здесь (концептуально) и здесь (и теоретический и practic), если Вы интересуетесь вопросом. Это - просто необычный прием, который может быть достигнут с частным наследованием. В то время как это воображение , это не ответ на вопрос.
Помимо основного использования просто частного наследования, показанного в FAQ C++ (связанный в комментариях других), можно использовать комбинацию частного и виртуального наследования к изоляция класс (в терминологии.NET) или сделать финал класса (в терминологии Java). Это не общее использование, но так или иначе я нашел это интересным:
class ClassSealer {
private:
friend class Sealed;
ClassSealer() {}
};
class Sealed : private virtual ClassSealer
{
// ...
};
class FailsToDerive : public Sealed
{
// Cannot be instantiated
};
Изолированный может быть инстанцирован. Это происходит от [1 111] ClassSealer и может назвать частного конструктора непосредственно, поскольку это - друг.
FailsToDerive не скомпилирует, как он должен звонить конструктор ClassSealer непосредственно (виртуальное требование наследования), но он не может, поскольку это является частным в Изолированный класс и в этом случае , FailsToDerive не является другом [1 116] ClassSealer.
<час>РЕДАКТИРОВАНИЕ
Это было упомянуто в комментариях, что это не могло быть сделано универсальным в то время использование CRTP. C++ 11 стандартов удаляет то ограничение путем обеспечения другого синтаксиса для оказания поддержки аргументам шаблона:
template <typename T>
class Seal {
friend T; // not: friend class T!!!
Seal() {}
};
class Sealed : private virtual Seal<Sealed> // ...
, Конечно, это все спорно, так как C++ 11 обеспечивает final
контекстное ключевое слово для точно этой цели:
class Sealed final // ...
Каноническое использование частного наследования "реализовано с точки зрения" отношений (благодаря 'Эффективному C++ Scott Meyers' для этой формулировки). Другими словами, внешний интерфейс наследующего класса не имеет никаких (видимых) отношений к наследованному классу, но он использует его внутренне для реализации его функциональности.
Я думаю критический раздел от , FAQ C++, Облегченный :
А законное, долгосрочное использование для частного наследования состоит в том, когда Вы хотите создать класс Fred, который использует код в классе Wilma и код от класса, Wilma должна вызвать функции членства от Вашего нового класса, Fred. В этом случае Fred называет non-virtuals в Wilma и вызовы Wilma (обычно чистый virtuals) сам по себе, которые переопределяются Fred. Это намного тяжелее относилось бы к составу.
, Если в сомнении, необходимо предпочесть состав по частному наследованию.
Иногда это могла быть альтернатива агрегирование , например, если Вы хотите агрегирование, но с измененным поведением aggregable объекта (переопределяющий виртуальные функции).
, Но Вы правы, это не имеет многих примеров от реального мира.
Я нахожу это полезным для интерфейсов (то есть абстрактные классы), что я наследовался, где я не хочу, чтобы другой код коснулся интерфейса (только наследующий класс).
[отредактированный в примере]
Берут пример связанный с вышеупомянутым. Высказывание, что
[...] класс Wilma должна вызвать функции членства от нового класса, Fred.
должен сказать, что Wilma требует, чтобы Fred был в состоянии вызвать определенные функции членства, или, скорее это говорит, что Wilma является интерфейсом . Следовательно, как упомянуто в примере
частное наследование не является злым; просто более дорого поддержать, так как это увеличивает вероятность, что кто-то изменит что-то, что взломает Ваш код.
комментарии к желаемому эффекту программистов, бывших должных отвечать нашим интерфейсным требованиям, или взламывающий код. И, с тех пор fredCallsWilma () защищен, только друзья и производные классы могут коснуться его т.е. наследуемый интерфейс (абстрактный класс), которого только наследующий класс может коснуться (и друзья).
[отредактированный в другом примере]
Эта страница кратко обсуждает закрытые интерфейсы (от еще одного угла).
Я использую все это время. Несколько примеров первое, что пришло на ум:
Типичный пример происходит конфиденциально из контейнера STL:
class MyVector : private vector<int>
{
public:
// Using declarations expose the few functions my clients need
// without a load of forwarding functions.
using vector<int>::push_back;
// etc...
};
Одно полезное использование частного наследования состоит в том, когда у Вас есть класс, который реализует интерфейс, который затем регистрируется в некотором другом объекте. Вы делаете тот интерфейс частным так, чтобы сам класс зарегистрировался и только конкретный объект, что его зарегистрированное в может использовать те функции.
Например:
class FooInterface
{
public:
virtual void DoSomething() = 0;
};
class FooUser
{
public:
bool RegisterFooInterface(FooInterface* aInterface);
};
class FooImplementer : private FooInterface
{
public:
explicit FooImplementer(FooUser& aUser)
{
aUser.RegisterFooInterface(this);
}
private:
virtual void DoSomething() { ... }
};
Поэтому класс FooUser может назвать закрытые методы FooImplementer через интерфейс FooInterface, в то время как другие внешние классы не могут. Это - большой шаблон для обработки определенных обратных вызовов, которые определяются как интерфейсы.
Иногда я нахожу полезным использовать частное наследование, когда я хочу выставить меньший интерфейс (например, набор) в интерфейсе другого, где реализация набора требует доступа к состоянию класса представления, подобным образом к внутренним классам в Java.
class BigClass;
struct SomeCollection
{
iterator begin();
iterator end();
};
class BigClass : private SomeCollection
{
friend struct SomeCollection;
SomeCollection &GetThings() { return *this; }
};
Затем, если SomeCollection должен получить доступ к BigClass, он может static_cast<BigClass *>(this)
. Никакая потребность иметь дополнительное место занимающего элемента данных.
Просто, потому что C++ имеет функцию, не означает, что это полезно или что это должно использоваться.
Я сказал бы, что Вы не должны использовать его вообще.
При использовании его так или иначе, ну, в общем, Вы в основном нарушаете инкапсуляцию и понижаете сцепление. Вы помещаете данные в один класс и добавляете методы, который управляет данными в другом.
Как другие функции C++, это может использоваться для достижения побочных эффектов, таких как изоляция класса (как упомянуто в ответе dribea), но это не делает это хорошей функцией.