C ++ переопределяет частный чистый виртуальный метод как публичный - PullRequest
0 голосов
/ 06 июня 2018

Почему это происходит?

http://coliru.stacked -crooked.com / a / e1376beff0c157a1

class Base{
private:
    virtual void do_run() = 0;
public:
    void run(){
        do_run();
    }
};

class A : public Base {
public:
    // uplift ??
    virtual void do_run() override {}
};


int main()
{
    A a;
    a.do_run();
}

Почему я могу переопределить PRIVATE виртуальный метод как публичный?

Ответы [ 5 ]

0 голосов
/ 29 июня 2018

Если намерение состоит в том, чтобы написать закрытый код для базового класса и предотвратить возможность его переопределения, реализуйте закрытую функцию в базовом классе и объявите ее final, в противном случае: Когда кто-то должен использовать частные виртуалы? ISOCPP.ORG FAQ

0 голосов
/ 06 июня 2018

Обратите внимание, что эта реализация не меняет способ доступа к базовому классу, и конструкция:

Base& b = a;
b.do_run();

не будет работать.

Я помню, что за этим стоит некоторое объяснение, более подробно описанное в «Эффективном C ++» Скотта Мейерса.Но ключевой практической особенностью является возможность использовать такую ​​гибкость в противоположном направлении, переопределять открытые члены базового класса частными функциями в производном классе, заставляя клиента использовать базовый класс в качестве интерфейса и не поддаваться искушению использовать непосредственнопроизводная, которая должна оставаться скрытой реализацией.

0 голосов
/ 06 июня 2018

В соответствии с https://en.cppreference.com/w/cpp/language/virtual#In_detail, перезаписывающими базовую virtual функцию-член, заботятся только об имени функции, параметрах, const / volatile-ness и квалификаторе ref.Он не заботится о типе возвращаемого значения, модификаторе доступа или других вещах, о которых вы могли бы подумать.

Связанная ссылка также особо отмечает, что:

Base :: vf не обязательно должен быть видимым (может быть объявлен закрытым или унаследованным с использованием частного наследования) для переопределения.

Ничто из того, что я могу найти, не дает явного разрешения на это, но правила переопределения не мешают этому.Это допускается благодаря virtual функциям и функциям, переопределяющим существующие и не запрещающим этот случай.

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

0 голосов
/ 06 июня 2018

Почему я могу переопределить виртуальный метод PRIVATE как общедоступный ???

Потому что вы смотрите, что базовый метод является приватным под неправильным углом.B::do_run «приватный» означает, что «только члены и друзья этого класса могут использовать его».Чтобы запретить производным классам переопределять его, нам нужен отдельный спецификатор, но мы можем просто сделать его не virtual.Класс A с другой стороны позволяет кому-либо звонить A::do_run(), и это зависит от дизайнера класса A.Так что вы не видите поднятия.

0 голосов
/ 06 июня 2018

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

См. здесь

...