|
|
|
Виртуальные методы класса
|
|||
|---|---|---|---|
|
#18+
Господа, собственно интересует в чем великая сила виртуальных методов класса ? Что-то читаю я читаю, как-то все закручено. Кто нить сможет мне внятно объяснить, чем такие методы отличаются от невиртуальных ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.03.2005, 08:37 |
|
||
|
Виртуальные методы класса
|
|||
|---|---|---|---|
|
#18+
Это механизм позднего(динамического) связывания. Т.е. когда известен метод, но не известен объект класса. То есть адрес функции вычисляется в рантайме из таблицы виртуальных методов объекта. Сааааамый стандартный пример. Базовый(абстрактный) класс "фигура". У него есть виртуальный метод "рисовать". Есть куча наследников у "фигуры": круг, квадрат, треугольник, линия и т.д. Создаем массив указателей на объект "фигура". В массив могут быть размещены указатели на любого наследника фигуры. Потому что они ведут себя КАК фигура. у них у всех есть СВОЙ метод рисовать. Когда мы бежим циклом по этомму массиву нам не важно, что там за объект, главное что у него был метод "рисовать" - он и вызовется. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.03.2005, 09:16 |
|
||
|
Виртуальные методы класса
|
|||
|---|---|---|---|
|
#18+
А если бы метод был не виртуальным ? ведь мне никто не мешает перегрузить невертуальный метод в наследнике. Так ? Или не так ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.03.2005, 09:19 |
|
||
|
Виртуальные методы класса
|
|||
|---|---|---|---|
|
#18+
Классический пример class Window { public: virtual void draw() { ... } void f() { ... } } class EditWindow : public Window { public: void draw() { ... } void f() { .... } } // обращаеися к наследнику через указатель на базовый класс Window *pEditWnd= new EditWindow(); // вызывается метод EditWindow::draw() pEditWnd->draw(); // вызывается Window::f() pEditWnd->f(); ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.03.2005, 10:46 |
|
||
|
Виртуальные методы класса
|
|||
|---|---|---|---|
|
#18+
luserА если бы метод был не виртуальным ? ведь мне никто не мешает перегрузить невертуальный метод в наследнике. Так ? Или не так ? никто не мешает, правильно. а как ты будешь разные классы в один массив складывать? но ты можешь сложить их в массив родительского типа, если у них у всех общий родитель. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.03.2005, 11:21 |
|
||
|
Виртуальные методы класса
|
|||
|---|---|---|---|
|
#18+
Предположим что есть следующая иерархия классов: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. Таким образом, невиртуальная ф-ция берется по типу указателя, а виртуальная - по типу объекта на который этот указатель ссылается. Физически это реализуется следующим образом: адрес call для невиртуальной ф-ции вычисляется на этапе компиляции, а для виртуальной - в классе заводится указатель на ф-цию и call делается с косвенной адресацией. Нужно это для того, чтобы в вершине иерархии классов не ломать голову над тем что будущий пользователь класса будет с ним делать (см. цитату) Базовый(абстрактный) класс "фигура". У него есть виртуальный метод "рисовать". Есть куча наследников у "фигуры": круг, квадрат, треугольник, линия и т.д. Создаем массив указателей на объект "фигура". В массив могут быть размещены указатели на любого наследника фигуры. Потому что они ведут себя КАК фигура. у них у всех есть СВОЙ метод рисовать. Так вот, в этом случае нужно метод Draw объявить в базовом классе Shape как виртуальный и не ломать голову над его отслеживанием в производных (которых тем более еще нет). Sorry, что так подробно написал, но использование виртуальных ф-ций (или неиспользование) - очень важная штука в ООП (по крайней мере в C++). P.S. У виртуальных ф-ций есть 3 минуса: 1. Увеличение размера объекта, т.к. для каждого экземпляра класса нужно хранить указатель на виртуальную ф-цию. 2. Замедление выполнения программы, т.к. вместо вызова call f_ptr используется call [f_ptr], т.е. требуется лишнее обращение к памяти. 3. Если в базовом классе определяется ф-ция с аргументами по умолчанию, то при ее переопределении в производном аргумент по умолчанию будет браться из базового класса: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. С уважением, Dubrov. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.03.2005, 15:41 |
|
||
|
|

start [/forum/topic.php?fid=57&fpage=411&tid=2033534]: |
0ms |
get settings: |
7ms |
get forum list: |
13ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
46ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
45ms |
get tp. blocked users: |
1ms |
| others: | 224ms |
| total: | 352ms |

| 0 / 0 |
