Pure virtual function call

ОблоТка: Pure virtual function call

Вопрос ΠΏΠΎ Π‘++. Π§Ρ‚ΠΎ Π·Π° ошибка Β«pure virtual function callΒ»? Π’ ΠΊΠ°ΠΊΠΎΠΉ ситуации ΠΎΠ½Π° ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ сгСнСрирована? ΠŸΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΡŒΡ‚Π΅ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄, приводящий ΠΊ Π½Π΅ΠΉ.

Π’Π΅, ΠΊΡ‚ΠΎ ΡΡ‚ΠΎΠ»ΠΊΠ½ΡƒΠ»ΠΈΡΡŒ с этой ошибкой Π² ΠΆΠΈΠ²ΠΎΠΌ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅ ΠΈ Π½Π΅ Π·Π½Π°Π»ΠΈ ΠΏΡ€ΠΎ Π½Π΅Ρ‘ Ρ€Π°Π½Π΅Π΅, навСрняка ΠΏΠΎΡ‚Ρ€Π°Ρ‚ΠΈΠ»ΠΈ Π½Π΅ΠΌΠ°Π»ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ Π½Π° ΠΎΡ‚Π»ΠΎΠ² этого Π±Π°Π³Π°. Π Π°Π·Π±Π΅Ρ€Ρ‘ΠΌ Π΅Π³ΠΎ ΠΏΠΎ ΠΏΠΎΠ»ΠΎΡ‡ΠΊΠ°ΠΌ.

ΠžΠΏΡ€ΠΎΡΡ‹ ΠΏΠΎΠΊΠ° Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚

Как Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ? ΠžΠ±Ρ‹Ρ‡Π½ΠΎ ΠΎΠ½ рСализуСтся Ρ‡Π΅Ρ€Π΅Π· Β«vtblΒ» (virtual table) β€” Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ с указатСлями Π½Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ экзСмпляр класса, содСрТащСго хотя Π±Ρ‹ ΠΎΠ΄Π½Ρƒ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΈΠΌΠ΅Π΅Ρ‚ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ __vtbl Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ vtbl для своСго класса. Π’ случаС с абстрактным классом ΠΈ чистой Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ, ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ всё Ρ€Π°Π²Π½ΠΎ Π΅ΡΡ‚ΡŒ, Π½ΠΎ Π½Π° стандартный ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ __pure_virtual_func_called(), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ Ρ‚Π°ΠΊΠΎΠΉ ошибкС. Но ΠΊΠ°ΠΊ Π΅Π³ΠΎ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ, вСдь прямая ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ° Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚Π»ΠΎΠ²Π»Π΅Π½Π° ΡƒΠΆΠ΅ Π½Π° этапС компиляции?

			#include <iostream>

class Base
{
public:
    Base() { init(); }
Β  Β Β ~Base() {}

Β  Β Β virtual void log() = 0;

private:
Β  Β Β void init() { log(); }	
};

class Derived: public Base
{
public:
Β  Β Β Derived() {}
Β  Β Β ~Derived() {}

Β  Β Β virtual void log() { std::cout << "Derived created" << std::endl; }
};

int main(int argc, char* argv[])
{
Β  Β Β Derived d;
Β  Β Β return 0;
}
		

Π Π°Π·Π±Π΅Ρ€Ρ‘ΠΌ, Ρ‡Ρ‚ΠΎ происходит ΠΏΡ€ΠΈ инстанцировании экзСмпляра ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° класса-ΠΏΠΎΡ‚ΠΎΠΌΠΊΠ°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ содСрТит vtbl.

Π¨Π°Π³ 1. Π‘ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π±Π°Π·ΠΎΠ²ΡƒΡŽ Ρ‡Π°ΡΡ‚ΡŒ Π²Π΅Ρ€Ρ…Π½Π΅Π³ΠΎ уровня:
Π°) Π£ΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ __vtbl Π½Π° vtbl Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ класса;
Π±) Π‘ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ экзСмпляра Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ класса;
Π²) Π’Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ Ρ‚Π΅Π»ΠΎ конструктора Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ класса.

Π¨Π°Π³ 2. НаслСдуСмая Ρ‡Π°ΡΡ‚ΡŒ(-ΠΈ) (рСкурсивно):
Π°) ΠŸΠΎΠΌΠ΅Π½ΡΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ __vtbl Π½Π° vtbl класса-ΠΏΠΎΡ‚ΠΎΠΌΠΊΠ°;
Π±) Π‘ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ класса-ΠΏΠΎΡ‚ΠΎΠΌΠΊΠ°;
Π²) Π’Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ Ρ‚Π΅Π»ΠΎ конструктора класса-ΠΏΠΎΡ‚ΠΎΠΌΠΊΠ°.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ взглянСм Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠ΅. НСслоТно Π΄ΠΎΠ³Π°Π΄Π°Ρ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒΡΡ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ класса Derived, Ρ‚ΠΎ Π½Π° шагС выполнСния конструктора Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ класса, ΠΎΠ½ сам ΠΏΠΎ сСбС Π±ΡƒΠ΄Π΅Ρ‚ Π΅Ρ‰Π΅ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒΡΡ Π±Π°Π·ΠΎΠ²Ρ‹ΠΌ классом ΠΈ Π΅Π³ΠΎ vtbl Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ класса. ΠžΠ±Ρ‹Ρ‡Π½ΠΎ компиляторы Π½Π΅ Π΄Π΅Ρ‚Π΅ΠΊΡ‚ΠΈΡ€ΡƒΡŽΡ‚ Ρ‚Π°ΠΊΠΎΠ΅ Π·Π°Ρ€Π°Π½Π΅Π΅ ΠΈ ошибка ловится Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² runtime.

Π’Ρ‹Π²ΠΎΠ΄: ΠΈΠ·Π±Π΅Π³Π°ΠΉΡ‚Π΅ Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Π² конструкторах ΠΈ дСструкторах, ΠΏΡ€ΠΈΡ‡Ρ‘ΠΌ ΠΊΠ°ΠΊ явных, Ρ‚Π°ΠΊ ΠΈ Ρ‡Π΅Ρ€Π΅Π· Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ.

ΠŸΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΏΡ€ΠΎ это ΠΌΠΎΠΆΠ½ΠΎ Π½Π°Β artima.comΒ ΠΈΠ»ΠΈ Π² ΠΊΠ½ΠΈΠΆΠΊΠ΅ Π‘ΠΊΠΎΡ‚Ρ‚Π° ΠœΠ°ΠΉΠ΅Ρ€ΡΠ° Β«Effective C++Β», совСт Π½ΠΎΠΌΠ΅Ρ€ 9.

Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅ΠΌ