Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Виртуальные методы класса / 6 сообщений из 6, страница 1 из 1
22.03.2005, 08:37
    #32972667
luser
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Виртуальные методы класса
Господа, собственно интересует в чем великая сила виртуальных методов класса ? Что-то читаю я читаю, как-то все закручено. Кто нить сможет мне внятно объяснить, чем такие методы отличаются от невиртуальных ?
...
Рейтинг: 0 / 0
22.03.2005, 09:16
    #32972712
dwl
dwl
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Виртуальные методы класса
Это механизм позднего(динамического) связывания. Т.е. когда известен метод, но не известен объект класса. То есть адрес функции вычисляется в рантайме из таблицы виртуальных методов объекта.

Сааааамый стандартный пример. Базовый(абстрактный) класс "фигура". У него есть виртуальный метод "рисовать". Есть куча наследников у "фигуры": круг, квадрат, треугольник, линия и т.д. Создаем массив указателей на объект "фигура". В массив могут быть размещены указатели на любого наследника фигуры. Потому что они ведут себя КАК фигура. у них у всех есть СВОЙ метод рисовать.

Когда мы бежим циклом по этомму массиву нам не важно, что там за объект, главное что у него был метод "рисовать" - он и вызовется.
...
Рейтинг: 0 / 0
22.03.2005, 09:19
    #32972722
luser
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Виртуальные методы класса
А если бы метод был не виртуальным ? ведь мне никто не мешает перегрузить невертуальный метод в наследнике. Так ? Или не так ?
...
Рейтинг: 0 / 0
22.03.2005, 10:46
    #32972949
Интегратор
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Виртуальные методы класса
Классический пример

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();
...
Рейтинг: 0 / 0
22.03.2005, 11:21
    #32973096
alex_k
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Виртуальные методы класса
luserА если бы метод был не виртуальным ? ведь мне никто не мешает перегрузить невертуальный метод в наследнике. Так ? Или не так ?
никто не мешает, правильно.
а как ты будешь разные классы в один массив складывать?

но ты можешь сложить их в массив родительского типа, если у них у всех общий родитель.
...
Рейтинг: 0 / 0
30.03.2005, 15:41
    #32989012
Dubrov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Виртуальные методы класса
Предположим что есть следующая иерархия классов:
Код: 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.
#include <iostream>

class Base
{
public:
  nvm(){std::cout<<"Non-virtual method (BASE)\n";}  //Non-Virtual Method
  virtual vm(){std::cout<<"Virtual method (BASE)\n";}  //Virtual Method
};

class Derived:public Base
{
  nvm(){std::cout<<"Non-virtual method (DERIVED)]\n";}  //Non-Virtual Method
  virtual vm(){std::cout<<"Virtual method (DERIVED)\n";}  //Virtual Method
};

int main()
{
  Base b;
  Derived d;

  Base *p;

  p=&b;
  p->nvm();  //Тут
  p->vm();    //  и тут все понятно

  p=&d;
  p->nvm();  // Вызов из BASE несмотря на то что он переопределен для DERIVED
  p->vm();   // Вызов из DERIVED

  return  0 ;
}

Таким образом, невиртуальная ф-ция берется по типу указателя, а виртуальная - по типу объекта на который этот указатель ссылается.
Физически это реализуется следующим образом: адрес 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.
class Base
{
public:
  virtual void f(int x= 1 ){...}
  ...
};

class Derived:public Base
{
public:
  virtual void f(int x= 2 ){...}
  ...
}

int main()
{
  Derived d;
 d.f();  //Будет вызван Derived::f(1);  // Т.е. с аргументом по умолчанию заданным в Base!!!
}
---
С уважением, Dubrov.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Виртуальные методы класса / 6 сообщений из 6, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]