Одновременное частное и публичное наследование в C++

Предположим, класс Y публично наследует класс X, Это возможно для класса Z унаследовать в частном порядке Y при публичном наследовании X?

Чтобы сделать это более понятным, предположим, X определяет публичные методы x1 а также x2, Y наследуется X, переопределяет x1 и предоставляет метод y, Позволяет ли C++ третий класс Z подкласс Y таким образом, что YРеализация x1 а также y доступны для него в частном порядке, в то время как внешний мир видит только его наследование X публично, т.е. имея только один публичный метод x2?

5 ответов

Решение

Да, это называется виртуальным наследованием.

struct X {
  virtual void x1();
  void x2();
};

struct Y : virtual X {
  void x1(); // overrides
  void y();
};

struct Z : private Y, virtual X { 

};

Люди не могут сделать z.y() или же z.x1() но они могут сделать z.x2() и может преобразовать Z* к X*, Однако, как только они это сделают, они могут позвонить converted->x1() а также converted->x2(), конечно.

Вы ничего не сказали о своей цели, но, похоже, вы действительно хотите сохранить Y хотя указатель

struct X {
  virtual void x1();
  void x2();
};

struct Y : X {
  virtual void x1(); // overrides
  void y();
};

struct Z : X { 
  virtual void x1() { // overrides
    /* uses y->x1 */ 
  }
  Y *y;
};

Это выглядит более знакомым для меня.

Конечно. Вы могли бы использовать using X::x2 в public: раздел. Конечно, если Y переопределяет x2, вы будете игнорировать это переопределение.

Я думаю, что использование оператора лучше заполняет эту роль, оно позволяет вам указать на Z, какие частные методы будут доступны:

class X
{
    public:
        virtual void x1() {}
        virtual void x2() {}

};

class Y: public X
{
public:
    virtual void x1() {}
};

class Z: private Y
{
public:
    using X::x2;

};

Прежде всего, я не совсем уверен, что понимаю ваше последнее предложение.

Позволяет ли C++ третьему классу Z подкласс Y таким образом, что реализация Y для x1 и y доступна для него в частном порядке, в то время как внешний мир видит, что он публично наследует X, т. Е. Имеет только один открытый метод x2?

Если Z публично наследует от Xтогда оба x1 а также x2 будет доступно: хотя доступность x2 может быть изменен в Zничто не мешает внешнему миру манипулировать Z через X указатель и вызов x2,

При этом, вы могли бы также иметь Z унаследовать в частном порядке от Y и публично из X хотя, как отметил Йоханнес, вы должны рассматривать виртуальное наследование как Z таким образом, будет наследовать дважды от X,


В зависимости от ваших потребностей, вы также можете захотеть взглянуть на шаблон декоратора (возможно, он совершенно не связан, но по какой-то причине я читаю ваш вопрос о том, чего вы хотите достичь):

class X
{
public:
    virtual void x1();
    virtual void x2();
};

class Y : public X
{
public:
    virtual void y();
    virtual void x1();
};

class Z : public X
{
public:
    explicit Z(X *x) : x_(x) {}

    virtual void x1() { x_->x1(); }
    virtual void x2() { x_->x2(); }

private:
    X *x_;
};

int main()
{
    Y y;
    Z z(&y);
}

В этом быстром и грязном примере кода Z это X (публичное наследство), но это повторное использование Y реализация.

Если вы используете не виртуальное наследование X хотя бы в одном месте, вы получите два отдельных подобъекта X с разными путями доступа и правами доступа.

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

Другие вопросы по тегам