Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.12.2007, 16:07   #1
Dunhil
 
Аватар для Dunhil
 
Регистрация: 19.12.2007
Сообщений: 4
По умолчанию Кто сможет разъяснить как и зачем использовать виртуальные функции в C++?

Привет! Гвоздь в следующем:
У меня есть три класса: для работы с датами(вычисления дня недели, кол-ва дней по дате и пр.х. ), для работы со временем и еще один класс наследующий от этих двух. Программа работает нормально все как надо, но препод озадачил, мол нужно использовать виртуальные функции. Что это такое примерно знаю, но к сожалению не настолько. С использованием еще не сталкивался. Плиз кто-нибудь разъясните что это такое! А желательно б еще исходник с этими функциями чтоб посмотреть как работает все это. Прилагаю исходник моей лабы. Написано на 6 билдере.
Вложения
Тип файла: rar Лаба.rar (685.0 Кб, 10 просмотров)
Есть только две бесконечные вещи: Вселенная и глупость. Хотя насчет вселенной я не уверен.
Альберт Энштейн.
Dunhil вне форума Ответить с цитированием
Старый 19.12.2007, 18:12   #2
kommunist
C# developer
Форумчанин
 
Аватар для kommunist
 
Регистрация: 03.10.2007
Сообщений: 393
По умолчанию

Цитата:
Сообщение от Dunhil Посмотреть сообщение
Плиз кто-нибудь разъясните что это такое! А желательно б еще исходник с этими функциями чтоб посмотреть как работает все это
Код:
#include "stdafx.h"
#include "iostream.h"

class Test1
{
public:
	void print();
	virtual void include(); // переопределяемая функция
};

void Test1::print()
{
	cout << "Start Print" << endl;
	include();		// в будующих реализация сюда включат код
	cout << "Cansel Print " << endl;
}

void Test1::include()  // в будующих реализация сюда включат код
{
     cout << "Test1" << endl;
}

class Test2 : public Test1
{
public:
	void include();	  // переопределили
};

void Test2::include() 	// наша реализация
{
	cout << "Test2" << endl;
}

void main()
{
Test2 t;
t.print(); 
}
Выполнение программы будет такое.
Start Print
Test2
Cansel Print
Press any key to continue
Функция которую можно переопределить в новом классе. А если ее не переопределять? То вызовется функция предка.
Код:
............
class Test2 : public Test1
{
};

void main()
{
Test2 t;
t.print(); 
}
Результат будет такой.
Start Print
Test1
Cansel Print
Press any key to continue
I like WPF
kommunist вне форума Ответить с цитированием
Старый 19.12.2007, 18:24   #3
Vedrus
ИСККОНный хакер
Форумчанин
 
Аватар для Vedrus
 
Регистрация: 08.11.2007
Сообщений: 195
По умолчанию

kommunist, человек спросил, зачем они нужны, а не как их писать. Буквы писать мы все умеем, а вот составлять из них слова...

Виртуальные функции позволяют потомку залазить внутрь родителя. Т.е. в родительском классе могут быть вызовы функций, содержание которых определяется в дочернем классе.

ЗЫ. Технически не очень точно, но концептуально доходчиво
ЗЫЫ. kommunist, уже голову сломал, но так до меня глупого и не дошло: а что изменится, если из Вашего кода virtual убрать? Может мат часть подучите? А то что человека информацией снабжаете, о которой и сами толком представления не имеете.
#define QUESTION bb || !bb
Vedrus вне форума Ответить с цитированием
Старый 19.12.2007, 23:25   #4
Dunhil
 
Аватар для Dunhil
 
Регистрация: 19.12.2007
Сообщений: 4
По умолчанию

Спасибо за исходник. Вот еще один вопросец по этой теме: допустим я работаю с объектом созданным из класса потомка, функция переопределена. Как вызвать функцию родительского класса из созданного объекта?
Есть только две бесконечные вещи: Вселенная и глупость. Хотя насчет вселенной я не уверен.
Альберт Энштейн.
Dunhil вне форума Ответить с цитированием
Старый 20.12.2007, 07:12   #5
Vedrus
ИСККОНный хакер
Форумчанин
 
Аватар для Vedrus
 
Регистрация: 08.11.2007
Сообщений: 195
По умолчанию

Функция переопределяется, когда нужно изменить функциональность. Если Вам нужна функциональность родителя – просто создайте объект от него. Если функция в потомке переопределена, то вызывать родительскую нельзя.

Вот вам обоим классы, в которых демонстрируется, для чего используются виртуальные функции
Код:
class CFigure
{
public:
	CFigure(); 
	CFigure(int c);
	CFigure(int c, Position pos);

	BOOL GetPos(Position &pos);
	BOOL SetPos(Position  pos);
	int GetColor();

	CFigure *GetFirstKiller();
	CFigure *GetNextKiller();
	CFigure *GetFirstDefender();
	CFigure *GetNextDefender();

	int GetCountKillers();
	int GetCountDefenders();

	BOOL FirstPossiblityStep(Position &pos);
	BOOL NextPossiblityStep(Position &pos);
protected:
	virtual BOOL GetSteps(int row, int col) = 0;
	Position curPos[2];

 	int color;
};

class CKnight : public CFigure
{
public:
	CKnight(): CFigure()       {}
	CKnight(int c): CFigure(c) {}
	CKnight(int c, Position pos): CFigure(c, pos) {}
protected:
	virtual BOOL GetSteps(int row, int col);
};

class CPawn : public CFigure
{
public:
	CPawn(): CFigure()       {}
	CPawn(int c): CFigure(c) {}
	CPawn(int c, Position pos): CFigure(c, pos) {}
protected:
	virtual BOOL GetSteps(int row, int col);
};

class CRook : public CFigure
{
public:
	CRook(): CFigure()       {}
	CRook(int c): CFigure(c) {}
	CRook(int c, Position pos): CFigure(c, pos) {}
protected:
	virtual BOOL GetSteps(int row, int col);
};

class CBishop : public CFigure
{
public:
	CBishop(): CFigure()       {}
	CBishop(int c): CFigure(c) {}
	CBishop(int c, Position pos): CFigure(c, pos) {}
protected:
	virtual BOOL GetSteps(int row, int col);
};

class CQueen : public CFigure
{
public:
	CQueen(): CFigure()       {}
	CQueen(int c): CFigure(c) {}
	CQueen(int c, Position pos): CFigure(c, pos) {}
protected:
	virtual BOOL GetSteps(int row, int col);
};

class CKing : public CFigure
{
public:
	CKing(): CFigure()       {}
	CKing(int c): CFigure(c) {}
	CKing(int c, Position pos): CFigure(c, pos) {}
protected:
	virtual BOOL GetSteps(int row, int col);
};
Как видите в базовом классе присутствует одна виртуальная функция, причём тела она не имеет (= 0 создаёт функцию без тела). Хоть у неё тело и отсутствует, но это не мешает остальным функциям активно её использовать.

Действия для обработки шахматных фигур ничем не отличаются друг от друга. Отличие только в манере ходить. Это отличие и вынесено в виртуальную функцию. Без виртуальной функции пришлось бы городить либо switch/case, либо в реализацию каждого класса фигуры вставлять все функции родителя, что, согласитесь, не рационально.

Наличие виртуальной функции без тела делает класс абстрактным, так что объект такого класса создать нельзя. Такой класс используется для создания потомков.

ЗЫ. Админы, перепишите обработчик “[code]”! А то что-то цвет как-то по велению удара бубна меняется.
#define QUESTION bb || !bb

Последний раз редактировалось Vedrus; 20.12.2007 в 07:24.
Vedrus вне форума Ответить с цитированием
Старый 20.12.2007, 14:19   #6
Dunhil
 
Аватар для Dunhil
 
Регистрация: 19.12.2007
Сообщений: 4
По умолчанию

Vedrus, большое спасибо за более подробное разъяснение, респект!
Есть только две бесконечные вещи: Вселенная и глупость. Хотя насчет вселенной я не уверен.
Альберт Энштейн.
Dunhil вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Люди добрые, помогите кто чем сможет. Chuprin2006 Microsoft Office Excel 4 11.06.2008 17:03
Одиночное наследование Виртуальные функции Brunette Помощь студентам 3 08.05.2008 19:23
Виртуальные машины! Marsik Софт 17 23.04.2008 20:33
Помогите кто сможет, пожалуйста b00s Microsoft Office Access 5 05.04.2008 12:57