Абстрактный класс и наследование - PullRequest
0 голосов
/ 09 декабря 2018
class MyInterface {
public:
    virtual void someFunction()= 0;
};

class X: public MyInterface {
private:
    virtual void doThis() {
        printf("This X");
    }
    virtual void doThat() {
        printf("That X");
    }
public:
    void someFunction() {
        doThis();
        doThat();
    }
};

class Y: public MyInterface, private X {
private:
    void doThat() {
        printf("That Y");
    }
};

MyInterface *iface= new Y();
Y->someFunction();

Исходя из аромата ООП Java, я пытаюсь обернуть голову вокруг модели ООП C ++.Я прочитал это: http://www.gotw.ca/publications/mill18.htm для предложений о том, как проектировать интерфейсы в C ++.Приведенный выше код является прямым применением (или небольшим изменением) правила, изложенного автором.Мой вопрос заключается в том, собирается ли приведенный выше код создать «This X» с последующим «That Y»?Что меня смущает, так это то, что автор рекомендует использовать virtual в сочетании с private.Я рассуждаю так: если функция private, как нам вообще ее переопределить?В приведенном выше коде предоставлено, что Y может использоваться в качестве правой части присваивания, так как мы открыто выводим данные из интерфейса.Когда мы вызываем someFunction() для него, так как мы не предоставляем явно реализацию внутри class Y, будет ли она использовать реализацию из class X?Затем, при условии, что он просматривает doThat() и снова использует Y s его реализацию?

1 Ответ

0 голосов
/ 09 декабря 2018

Код имеет несколько проблем.Вот рабочий пример:

class MyInterface
{
public:
    virtual ~MyInterface() { }
    virtual void someFunction() = 0;
};

class X : public MyInterface
{
private:
    virtual void doThis()
    {
        printf("This X\n");
    }
    virtual void doThat()
    {
        printf("That X\n");
    }

public:
    void someFunction()
    {
        doThis();
        doThat();
    }
};

class Y : public X
{
private:
    void doThat()
    {
        printf("That Y\n");
    }
};

int main()
{
    MyInterface *iface = new Y();
    iface->someFunction();
    delete iface;
}

Пояснения

  1. Вам нужно использовать class Y : public X, чтобы иметь возможность использовать реализацию void X::someFunction()

    К сожалению, в C ++ нет реального интерфейса, и есть только обходной путь, использующий чисто виртуальный класс.Этот обходной путь с двумя родителями имеет свои ограничения (см. Ниже) .И поэтому также неплохо добавить деструктор в определение интерфейса.

    Когда вы используете class Y: public MyInterface, private X, вам необходимо предоставить пользовательскую реализацию MyInterface::someFunction().У вас есть два родительских класса и someFunction() у обоих родителей (X и MyInterface) .Это необходимо, даже если есть только одна реализация функции.Поэтому вам нужно указать, какой родительский класс будет использоваться для реализации.Ошибка:

    'Y': невозможно создать экземпляр абстрактного класса

    Вы также получаете сообщение об ошибке при удалении интерфейса (попробуйте использовать интерфейс из X) .Причина проста: когда X является закрытым, реализация не является общедоступной и не может использоваться в качестве интерфейса.

    «приведение типа»: преобразование из «Y *» в «MyInterface *»'существует, но недоступен

  2. Вы используете класс как тип в Y->someFunction();

  3. Понятия не имею, почему выможет переопределить частную виртуальную функцию.Сейчас я в основном работаю в C #, и эта «особенность» C ++ - то, чего я не понимаю.Вы правы, что это должен быть плохой код, но он работает (по крайней мере, в Visual Studio 2017) .

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

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