- Чи можна мати не віртуальний деструктор у класі, якщо один з методів абстрактний?
- Як спрацює поліморфний виклик через this в базовому класі:
- У конструкторі.
- У віртуальному деструкторі.
- У звичайному деструкторі.
- Чи можна унаслідувати конструктор базового класу?
- В яких випадках визначають абстрактний член класу (деструктор, метод)?
1. Чи можна мати не віртуальний деструктор у класі, якщо один з методів абстрактний?
Так, синтаксично це не є помилкою, проте абстрактний метод вказує на використання поліморфізму. Якщо хоча б один з класів має (чи в майбутньому матиме) нетривіальний деструктор, то він ніколи не викликатиметься. Щоб уникнути подібних логічних помилок в програмі, правило просте: якщо хоча б один метод віртуальний, то деструктор базового класу також має бути віртуальним.
2. Як спрацює поліморфний виклик через this в базовому класі:
- В конструкторі.
- В віртуальному деструкторі.
- В звичайному деструкторі.
В деструкторі, незалежно від того віртуальний він чи ні, поліморфізм працює без ніяких особливостей.
В конструкторі поліморфізм через this не працює, бо при виклику конструктора класу-предка об'єкт класу-нащадка ще не існує. Через це завжди викликатиметься метод класу, який конструюється в даний момент (метод класу-предка). Наступний код, де базовий клас викликає віртуальний метод в конструкторі, двічі виведе Base, а не Base і Derived:
#include <iostream>
struct Base {
Base() { this->print();}
virtual void print() { std::cout << "Base" << std::endl; }
};
struct Derived : public Base {
virtual void print() { std::cout << "Derived" << std::endl; }
};
int main() {
Base* base;
base = new Base(); delete base;
base = new Derived(); delete base;
return 0;
}
3. Чи можна унаслідувати конструктор базового класу?
Так, конструктори в C++ не наслідуються за замовчуванням, але їх можна наслідувати явно за допомогою директиви using:
struct Base {
Base(int a, int b) {}
};
struct Derived : public Base {
using Base::Base;
};
Виклик конструктора з параметрами, наприклад, Derived(1, 2), буде синтаксично коректним в такому випадку. Без using, такого конструктора в Derived не буде і виникне помилка на етапі компіляції.
4. В яких випадках визначають абстрактний член класу (деструктор, метод)?
Абстрактний деструктор визначають завжди. Якщо його не визначити, але в коді використовувати об'єктів класів-нащадків, то він викликатиметься неявно. Через це виникне помилка на етапі лінкування, що деструктор базового класу оголошений, але не має визначення ("undefined reference").
Абстрактний метод визначають, якщо він має явно викликатись у класі-нащадку:
struct Base {
virtual void print() = 0;
};
void Base::print() { std::cout << "Base" << std::endl; }
struct Derived : public Base {
virtual void print() { this->Base::print(); }
};
Добавить комментарий