C ++ Виртуальный или нет? - PullRequest
       41

C ++ Виртуальный или нет?

1 голос
/ 05 декабря 2011

Почему вы хотите объявить функцию не виртуальную в иерархии наследования с более чем двумя уровнями? Может кто-нибудь дать мне пример?

Я знаю, в чем разница и что происходит, но я не могу понять, почему и когда вы хотите это сделать.

Ответы [ 5 ]

6 голосов
/ 05 декабря 2011

С семантической точки зрения: чтобы его нельзя было переопределить.

С практической точки зрения: если виртуальных функций нет, тогда нет необходимости в vptr, поэтому каждый экземпляр будет занимать немного меньше памяти. Кроме того, как говорит @Billy в комментарии, это означает, что функция-член не будет вызываться косвенно.

2 голосов
/ 05 декабря 2011

Первый вопрос: почему вы хотите иерархию наследования более двух уровней?Наиболее частой иерархией наследования, безусловно, будет абстрактный базовый класс и один уровень классов, которые вытекают из него.(По крайней мере, когда деривация используется для реализации наследования ОО - нередко использование деривации C ++ для других целей.)

Существует два частых паттерна, где встречается более глубокая иерархия наследования.Первое происходит, когда вы расширяете интерфейс;на практике нет большой разницы между этим и производным от единственной абстрактной базы, и было бы ошибкой выводить класс, обеспечивающий реализацию в любом случае.Во-вторых, реализация настраивается с использованием шаблона метода шаблона.И в этом случае вы действительно хотели бы отобразить в нем функции реализации final: любой, унаследованный от этого класса, должен реализовывать только новые виртуальные функции, используемые для определения настройки;в противном случае вы, вероятно, не сможете гарантировать все необходимые инварианты.

2 голосов
/ 05 декабря 2011

Основная причина этого заключается в том, что когда вы делаете метод виртуальным, вы говорите подклассам: «Идите дальше и изменяйте поведение здесь». Когда вы делаете это, вы ограничиваете возможность изменения базового класса. По сути, тогда подклассы могут легко оказаться в зависимости от деталей реализации базового класса, а когда кто-то пытается изменить базовый класс, разбить непостижимо большой объем кода.

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

1 голос
/ 05 декабря 2011

Вы хотите предотвратить переопределение производными классами, потому что ...

  1. Виртуальные функции предоставляют части вашего класса производному классу, которые вы, возможно, не хотите раскрывать - если производный класс переопределяет это, изменение того, как и когда вызывается функция, может нарушить производный класс.
  2. Производительность / встраивание. Виртуальная функция получения в базовом классе - это плохо, если что-то действительно критично для производительности.
  3. Вы вызываете функцию из своего конструктора (базового класса), поэтому переопределение функции не имеет смысла. (При вызове из конструктора базового класса всегда вызывается версия функции базового класса).
0 голосов
/ 05 декабря 2011

/ * мы рассмотрим, почему нет необходимости объявлять все функции в многоуровневых наследование как виртуальное, потому что есть некоторые функции / действия, которые должны быть
в исполнении только BASE CLASS. надеюсь, вы понимаете этот простой пример здесь родители могут видеть там детей табель успеваемости и могут подписать его. в то время как Big_brother может только читать отчет, но не может подписать, аналогично small_brother также не может подписать, но может прочитать его; * /

#include<cstring>
#include<iostream>
using namespace std;

class parent
{
private:
    int signeture;
protected:
    int read;
public:
    parent():read(0),signeture(0){}
    void sign()
    {
    signeture=1;
    cout<<"\nparent sign";
    }
    virtual void readReport()
    {
    cout<<"\nDAD can also read"<<read;
    }
};


class big_brother:public parent
{
public:
void readReport()
{
    read=3;
    cout<<"\nbig brother card"<<read;
}
//some other function which only Big_brother can performed are 
//declared here asnon_virtual

};



class small_brother:public big_brother
{
public:
void readReport()
{
    read=4;
    cout<<"\n small brothers card"<<read;

}
};
int main()
{
parent x;
big_brother y;
small_brother z;
x.readReport();
y.readReport();
z.readReport();
cout<<"only parent can sign";
x.sign();

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