Допустимо ли «скрывать» виртуальную функцию базового класса, делая ее чисто виртуальной в производных классах? - PullRequest
0 голосов
/ 23 января 2019

Рассмотрим пример:

#include <iostream>

class A {
    public:
    virtual void f();
};

void A::f()
{
    std::cout << "f() from A\n";
}

class B: public A {
    public:
    virtual void f() = 0;
};

class C: public B {
    public:
    void f();
};

void C::f()
{
    std::cout << "f() from C\n";
}

int main()
{
    C o;
    o.f();
}

A::f() реализация «скрыта» от класса C, которая обеспечивает собственную реализацию для f() - эффективно делая A::f() более или менее бессмысленным.Я вижу небольшую ценность в таком дизайне иерархии классов, но мой вопрос, является ли это действительным C ++ или просто «работает» (например, неопределенное поведение)?

Ответы [ 5 ]

0 голосов
/ 23 января 2019

Насколько я вижу, нет неопределенного поведения = 0 означает только то, что производные классы должны переопределять его. Но вы все равно можете предоставить внешнее определение для этой функции в том же классе.

0 голосов
/ 23 января 2019

Это безопасно достигнет цели, требующей от автора C предоставить реализацию для f().

Я бы спросил, зачем это нужно & mdash; если базовая реализация не является «допустимой» в вашем проекте, то почему она существует и / или почему она virtual?

Они все равно могут вызывать A::f(), так что вопрос о том, можно ли это считать «сокрытием», открыт для дискуссий.

0 голосов
/ 23 января 2019

Это явно разрешено и поддерживается стандартом (см., Например, это онлайн-проект стандарта C ++), и, следовательно, явно не неопределенное поведение:

10.4 Абстрактные классы

5 [Примечание: абстрактный класс может быть получен из класса, который не является абстрактным, и чисто виртуальная функция может переопределять виртуальную функцию, которая не является чистой.- конец примечания]

В результате ваш класс B становится абстрактным, и любой подкласс - если он также не должен быть абстрактным - должен определять f() затем;реализация в классе A все еще может быть вызвана через A::f(), так что это - с точки зрения повторного использования реализации - не бессмысленно.

0 голосов
/ 23 января 2019

Это допустимый и четко определенный C ++.

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

0 голосов
/ 23 января 2019

мой вопрос, является ли это действительным C ++ или просто "работает" (например, неопределенное поведение)?

Поведение программы хорошо определено.

эффективно делает A::f() более или менее бессмысленным.

Конечно, если вы никогда не вызываете функцию, то определение функции действительно не нужно. Для пояснения, функция должна быть объявлена ​​чисто виртуальной, если вы решили опустить определение (обратное неверно; вы можете определить чисто виртуальную функцию).

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