Закрытые переопределенные виртуальные функции в производном классе - PullRequest
4 голосов
/ 18 октября 2019

Есть ли смысл делать виртуальные функции-члены переопределенными из базового класса частными, если они являются общедоступными в базовом классе?

struct base {
    virtual void a();
};

struct derived : base {
// ...
private:
    void a() override;
};

Ответы [ 4 ]

1 голос
/ 18 октября 2019

Если вы вынуждены выполнить двухфазную конструкцию для класса реализации (т.е. иметь метод init(), а также или вместо конструктора, который должен быть вызван (я знаю, но есть причины), тогдаэто останавливает вызов любых / других / методов непосредственно для указателя экземпляра перед тем, как передать его обратно в качестве указателя интерфейса. 1003 * Другая причина в том, что вы просто / не нуждаетесь в записи public: в окончательном объявлении класса реализации, так что по умолчанию все является закрытым. Но почему бы вы сделали это и использовали struct вместо класса, я не знаюВозможно, это было преобразовано из класса в какой-то момент из-за войны стиля?

1 голос
/ 18 октября 2019

Глядя на ваш дизайн, я вижу, что никто не может вызвать derived::a напрямую, но только через интерфейс base.

Есть ли смысл? Учтите, что когда у нас есть экземпляр derived, мы всегда можем повысить его базу, поэтому, если

derived d;

, а d.a() не будет компилироваться, мы всегда можем сделать

base & b = d;
b.a(); //which actually calls derived::a

Другими словами: derived::a - это не , что, в конце концов, приватно, и я бы не одобрил этот дизайн, который может сбить пользователя с толку.

Все изменится, есличлены * private в derived также являются приватными в base: на этот раз ясно, что их просто нельзя вызвать напрямую, вне base или derived.

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

struct base 
{
    void dosomething(bool x)
    {
        if(x)
        {
            do_this();
        }
        else
        {
            do_that();
        }
    }
private:
    virtual void do_this(){}
    virtual void do_that(){}
};

Таким образом, производный класс можетбыть похожим на:

struct derived : base 
{
private:
    void do_this() override { }
    void do_that() override { }
};

, и никакие другие классы не могут вызывать их, если только он сам не расширил base:

derived d;
d.dosomething(true); //will call do_this() in derived
d.dosomething(false); //will call do_that() in derived

d.do_that() //won't compile
1 голос
/ 18 октября 2019

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

ЕслиВы хотите ограничить некоторые функции из базового класса, сделать частное / защищенное наследование и через ключевое слово using объявить, какие базовые методы вы хотите защитить / сделать общедоступными в производном классе.

0 голосов
/ 18 октября 2019

Применяется то же рассуждение, что и для не виртуальных методов: если только сам класс должен вызывать его, сделайте его закрытым.

Рассмотрим шаблонный метод :

struct base {
    void foo() { a() ; b(); }
    virtual void a() = 0;
    virtual void b() = 0;
};

struct derived : base {
private:
    void a() override {}
    void b() override {}
};
int main()
{
   derived().foo();
}

Возможно a и b должны были быть protected, но в любом случае derived может изменитьсядоступность и требует некоторой документации, чтобы derived знал, как предполагается реализовать a и b.

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