Есть ли способ «удалить» чисто виртуальную функцию? - PullRequest
5 голосов
/ 09 июня 2009

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

class derivative: public base
{
public:
    int somevariable;
    void somefunction();
};

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

int purevirtfunc(){return 0;}

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

Ответы [ 11 ]

40 голосов
/ 09 июня 2009

Если ваш производный класс не «использует» чисто виртуальную функцию базового класса, то либо производный класс не должен быть производным от базы, либо PVF не должен быть там. В любом случае, ваш дизайн виноват и нуждается в переосмыслении.

И нет, нет способа удалить PVF.

14 голосов
/ 09 июня 2009

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

Ваши варианты:

  1. Реализуйте метод, как вы описываете (если он будет закрытым, это означает, что его не следует использовать)
  2. Измените иерархию классов, чтобы учесть изменение дизайна.
9 голосов
/ 09 июня 2009

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

5 голосов
/ 09 июня 2009

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

1 голос
/ 09 июня 2009

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

1 голос
/ 09 июня 2009

Нет. Либо предоставьте реализацию по умолчанию в базовом классе, либо простую реализацию в производном классе, как вы предложили.

1 голос
/ 09 июня 2009

Когда вы наследуете от класса, который имеет чисто виртуальные функции, вы ДОЛЖНЫ реализовать эти функции. Если вы этого не сделаете, то ваш производный класс также является абстрактным, и вы не можете создать объект из производного класса.

0 голосов
/ 18 декабря 2011

Нет, нет. Соглашение в языках с поздним связыванием, когда возникает такая ситуация (как это может происходить на законных основаниях, но рассмотрите свой дизайн, чтобы увидеть, можно ли переместить этот метод в другое место, возможно, в его абстрактный класс), заключается в создании исключения и обеспечении того, чтобы пользователи этого Метод знает, что некоторые реализации могут вызывать это исключение.

0 голосов
/ 18 декабря 2011

Не могли бы вы просто сделать

class Foo {
public:
    virtual void foo() = 0;
};

class Bar {
public:
    virtual void foo() = delete;
};
0 голосов
/ 09 июня 2009

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

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

Я не знаю, поможет ли это вам с вашей проблемой или нет.

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