![]() |
![]() |
![]() |
|
С++ Виртуальные методы в конструкторе/деструкторе | ☑ | ||
---|---|---|---|---|
0
Ненавижу 1С
гуру
31.03.11
✎
16:25
|
верно ли в С++:
1. в деструкторе нельзя вызывать чисто виртуальные (абстрактные) методы 2. подозреваю что и в конструкторе тоже 3. в деструкторе вызов виртуального метода происходит как не виртуального 4. аналогично в конструкторе |
|||
1
holydel
31.03.11
✎
16:53
|
1. в дестркторе кого? в деструкторе базового класса - можно - вызовется абстрактный метод базового класса(если есть реализация) в деструкторе производного класса - можно вызвать явно, через ::.
2. аналогично. 3. а как же иначе? мы вызываем один метод класса из другого метода класса (пусть деструктора). все вызовы методов класса будут невиртуальными. 4. аналогично. [code] #include <iostream> class Abba { private: int a; void SetA(int a_) { std::cout<<"StA"<<std::endl; a = a_; } public: int GetA() { return a; } virtual int VFunc() = 0; Abba() { std::cout<<"Abba ctr"<<std::endl; SetA(-1); VFunc(); } ~Abba() { std::cout<<"Abba dtr"<<std::endl; SetA(1); VFunc(); } }; int Abba::VFunc() { std::cout<<"Abba VFunc"<<std::endl; a = 3; return 5; } class Bitls : public Abba { public: virtual int VFunc() { std::cout<<"Bitls VFunc"<<std::endl; return Abba::VFunc()+1; } Bitls() { std::cout<<"Bitls ctr"<<std::endl; VFunc(); Abba::VFunc(); } ~Bitls() { std::cout<<"Bitls dtr"<<std::endl; VFunc(); Abba::VFunc(); } }; int main(int argc, const char* argv[]) { { Bitls b; } int a; std::cin>>a; return 0; } [/code] |
|||
2
Rabbit
31.03.11
✎
17:10
|
Я так скажу: ТВМ, или аналоги создаются до вызова тела конструктора и уничтожаются после вызова тела деструктора.
|
|||
3
Ненавижу 1С
гуру
31.03.11
✎
17:10
|
а как же это?
class A { public: virtual int Test1()=0; virtual int Test2(){return 0;} A() { //std::cout<<Test1(); закоментировано по причине ошибки компиляции std::cout<<Test2(); //выдает 0 } }; class B:public A { public: virtual int Test1(){return 1;} virtual int Test2(){return 1;} }; B* b = new B(); delete b; |
|||
4
Fragster
гуру
31.03.11
✎
17:13
|
(0) у меня 1ска что-то стала вылетать периодически с pure virtual function call - предположительно после включения управляемых блокировок
|
|||
5
Rabbit
31.03.11
✎
17:13
|
(3) а что такое экземпляр абстрактного класса?
|
|||
6
Ненавижу 1С
гуру
31.03.11
✎
17:15
|
(1) у вас нет абстрактного метода
(5) а где ты такое увидел? |
|||
7
Rabbit
31.03.11
✎
17:16
|
(6) A()
{ //std::cout<<Test1(); закоментировано по причине ошибки компиляции std::cout<<Test2(); //выдает 0 } Это конструктор чего? И у компилятора наверно ключики какие-то есть. |
|||
8
Ненавижу 1С
гуру
31.03.11
✎
17:17
|
(7) это конструктор абстрактного класса, но экземпляров абстрактного класса я не создавал
|
|||
9
Rabbit
31.03.11
✎
17:19
|
(8) Тебе их не дали создать.
|
|||
10
Ненавижу 1С
гуру
31.03.11
✎
17:19
|
(9) ну и я не оспариваю этот факт
|
|||
11
Rabbit
31.03.11
✎
17:21
|
(10) иначе тебе бы пришлось ответить на (5)
|
|||
12
Ненавижу 1С
гуру
31.03.11
✎
17:22
|
(11) вот казуар ты, экземпляров абстрактного класса быть не может
|
|||
13
Rabbit
31.03.11
✎
17:23
|
(12) >> 3. в деструкторе вызов виртуального метода происходит как не виртуального
4. аналогично в конструкторе А это откуда? |
|||
14
Ненавижу 1С
гуру
31.03.11
✎
17:24
|
(13) но деструктор то абстрактного базового класса все равно вызывается ведь
|
|||
15
Sk0rp
31.03.11
✎
17:36
|
(0) Давай я кратко теорию расскажу, а ты сам решай какой выбор есть у компилятора:
1. Виртуальные функции имеют смысл когда есть наследование. 2. Для вызова правильной виртуальной функции каждый производный класс пишет указатель на свой вариант переопределяемой функции в таблицу виртуальных функций. 3. При создании класса он конструируется так: сначала базовый класс, потом его производный, потом производный производного и т.д. 4. Разрушение идет строго в обратном порядке. Из пункта 3 следствие, что на момент работы конструктора базового класса, информации о производных классах еще нет, соответственно знать какие там будут переопределены виртуальные функции нельзя. Значит в конструкторе можно вызвать виртуальные функции только этого класса или базового. Это может вызвать существенную неопределенность: при вызове функции в конструкторе вызывается одна, а после конструктора уже вызовется другая функция. В деструкторе все аналогично: производный объект уже разрушен и указатель на таблицу виртуальных функция изменен - будет вызвана та еж функция, что вызвалась бы в конструторе, но не та, что вызывалась во время жизни объекта. Поэтому в целях уменьшения неразберихи это обычно запрещется. Впрочем функцию по прежнему можно вызвать невиртуально (явно через 2 двоеточия указав класс из которого её взять) |
|||
16
Sk0rp
31.03.11
✎
17:41
|
(3) Надо различать виртуальные и "чисто виртуальные" (pure virtual) функции. Первые обязательно имеют хоть какое-то тело в базовом классе и её хотя-бы теоритически можно вызвать. Чисто виртуальные задают интерфейс для производных классов. Они обязательно должны быть переопределены для возможности создать объект. И вызвать из можно не ранее, чем она определена.
Компилятор можно обмануть, например через явное приведения указателя, в этом случае получается исключение: pure virtual call |
|||
17
Rabbit
31.03.11
✎
17:51
|
(15) На самом деле всё было нетак
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |