Наследование чистой виртуальной функции - PullRequest
0 голосов
/ 29 апреля 2018

Может кто-нибудь прояснить эти понятия и ответить на эти вопросы. Заранее спасибо.

Класс A является базовым классом и имеет чисто виртуальную функцию с именем display.

class A 
{ 
  public:
       virtual void display()const=0;

};

Класс B является производным классом, который наследует класс A. Кроме того, B отменяет функцию отображения,

class B:public A 
{ 
  public:
       void display()const{cout<<"Always"<<endl;}

};

В1: Теперь B содержит 1 переопределенный дисплей и 1 унаследованный чистый виртуальный дисплей, верно? Или чисто виртуальный из-за переопределения перестает существовать.

Я спрашиваю это, потому что последний вопрос, с которым я сталкиваюсь, это: Q2: Предположим, B переопределил функцию отображения, теперь, если есть новый класс

class C:public B 
{ 
  public:
};

Теперь у меня есть четкое представление о том, что все производные классы первого уровня (например, B) должны иметь обязательство переопределять чисто виртуальную функцию (происходящую из класса A), предположим, что они переопределяют ее. что теперь, если существует новый класс C, производный от одного из классов, производных от первого уровня (класс B), потребуется ли ему также переопределить чисто виртуальную функцию (display) или он не потребуется, так как был переопределен в классе B, а C наследует B (следовательно, получил переопределение функции отображения?

Ответы [ 4 ]

0 голосов
/ 29 апреля 2018

Теперь B содержит 1 переопределенный дисплей и 1 унаследованный чистый виртуальный дисплей, верно?

NO.

Вы можете понять это так:

Или чисто виртуальный из-за переопределения становится несуществующим.

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

Если B переопределить функцию, то ее указатель на функцию помещается в виртуальную таблицу.

C не нужно переопределять. Он получит функцию от B.

C может переопределить функцию. Затем его указатель войдет в виртуальную таблицу.

B не нужно переопределять. Но тогда нельзя создать переменную из B. Тогда C должен переопределить функцию (если вы хотите переменную)

0 голосов
/ 29 апреля 2018

Предположим, существует виртуальный базовый класс A

class A 
{ 
  public:
       virtual void display()const=0;

};

.

class B:public A 
{ 
  public:
       void display()const{cout<<"Always"<<endl;}

};

В1: Теперь B содержит 1 переопределенный дисплей и 1 унаследованный чистый виртуальный дисплей, верно? Или чисто виртуальный из-за переопределения становится несуществующим.

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

Q2: Предположим, B переопределил функцию отображения. Теперь, если появился новый класс C

class C : public B 
{ 
    ...
};

также необходимо переопределить чисто виртуальную функцию (отображение)?

Нет, C получает все функции от B, включая конкретную реализацию display()

Однако C может опционально снова переопределить функцию display(). И так далее. Нет ограничений на количество подклассов класса.

0 голосов
/ 29 апреля 2018

Q1: теперь B содержит 1 переопределенный дисплей и 1 унаследованный чистый виртуальный дисплей, верно? Или чисто виртуальный из-за переопределения становится несуществующим.

Ваш первый вопрос здесь не имеет смысла. Класс B наследует чистый виртуальный от A и переопределяет его. Он также не «содержит».

A::display() на самом деле существует как правильно именованная сущность, на которую можно ссылаться в B. Например, если определено A::display();

class A 
{ 
    public:
        virtual void display()const=0;
};

//   yes, defining a pure virtual function is allowed, albeit optional 
void A::display() const       
{
    std::cout << "A!\n";
}

тогда B::display() может позвонить.

class B:public A 
{ 
   public:
       void display()const
       {
           A::display();
           std::cout<<"Always"<<endl;
       }
};

так что A::display() и B::display() существуют в этом случае. Приведенный выше код для B::display() скомпилируется (поскольку компилятор распознает и A::display(), и B::display() как отдельные имена функций) независимо от того, определен A::display() или нет. (Если A::display() не определено, компоновщик обычно сообщает об отсутствующем символе).

Q2: Предположим, B переопределил функцию отображения. Теперь, если есть новый класс

class C:public B 
{ 
    public:
};

Теперь мне ясно, что все производные классы первого уровня (например, B) должны иметь обязательную силу, чтобы они переопределяли чисто виртуальную функцию (происходящую из класса A), предположим, что они переопределяют ее. что теперь, если существует новый класс C, производный от одного из классов, производных от первого уровня (класс B), потребуется ли ему также переопределить чисто виртуальную функцию (display) или он не потребуется, так как был переопределен в классе B, а C наследует B (следовательно, получил переопределение функции отображения?

Если B переопределяет display(), то C наследует display() как нечистую виртуальную функцию. Это означает, что если можно создать экземпляр B, то можно C.

Если C не переопределяет унаследованный display(), тогда some_c->display() вызовет версию, унаследованную от B, т.е. B::display().

Если C переопределяет display() - что разрешено для любой унаследованной виртуальной функции - тогда он может реализовать C::display() любым необходимым способом.

0 голосов
/ 29 апреля 2018

Q1: теперь B содержит 1 переопределенный дисплей и 1 унаследованный чистый виртуальный дисплей, верно?

Я не знаю, что вы подразумеваете под этим.

C не нужно переопределять display. Если этого не произойдет, он будет использовать тот, который унаследован от B.

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