Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Виртуальные функции 
V
    Опции темы
Hagrael
Дата 17.7.2011, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 143
Регистрация: 26.6.2011

Репутация: нет
Всего: нет



Здравствуйте, форумчане. Не затруднитесь ли вы мне объяснить, для чего нужны?
PM MAIL   Вверх
bsa
Дата 17.7.2011, 16:00 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Они нужны для унификации интерфейса доступа к разным объектам.
Например, разные программы управляются мышкой и клавиатурой. Но выполняют они совершенно разные вещи. Так вот, мышка и клавиатура - это интерфейс. Он одинаков для всех, но разные программы реагируют на действия по разному.
Так же и виртуальные функции. У тебя есть класс:
Код
class Window
{
public:
//...
    virtual void draw() {}
    virtual void processEvent(Event &e) {}
//...
};
Он объявляет интерфейс доступа к объектам типа окна. Но вызов данных функций ничего не делает. Теперь ты делаешь класс, например LineEdit, наследуясь от Window. Заменяешь методы draw() и processEvent(). Теперь ОС, даже не зная, что у тебя объект на самом деле LineEdit, так же как и для Window вызывает эти методы, получая уже другой эффект.
Код
Window *w;
//...
w = new LineEdit;
//...
w->processEvent(event);
//...
w->draw();
//...


Это сообщение отредактировал(а) bsa - 17.7.2011, 16:01
PM   Вверх
boostcoder
Дата 17.7.2011, 16:04 (ссылка)  | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



Цитата(Hagrael @  17.7.2011,  15:21 Найти цитируемый пост)
объяснить

в книжках найдешь объяснение.
что за вопросы... это форум а не бесплатные курсы по изучению ЯП.

Это сообщение отредактировал(а) boostcoder - 17.7.2011, 16:04
PM WWW   Вверх
Сыроежка
Дата 17.7.2011, 19:10 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 24.6.2011

Репутация: 1
Всего: 1



Цитата(Hagrael @  17.7.2011,  15:21 Найти цитируемый пост)
Здравствуйте, форумчане. Не затруднитесь ли вы мне объяснить, для чего нужны? 


Сначала хотел бы вам посоветовать, не обращать внимание на грубость некоторых здесь присутствующих. Ьерегите нервы.smile

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

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

Самое лучший способ понять их назначение, это составить классический пример с одним базовым классом с именем Shape, который задает интерфейс, и производными классами типа Circle, Triangle, Rectangle. Затем создать все производные классы и попробовать через указатель на базовый класс, вызвать виртуальную функцию для производных классов.
То есть я хотел сказать, что на примере понять это проще.smile


Это сообщение отредактировал(а) Сыроежка - 17.7.2011, 19:16
PM MAIL   Вверх
ZVano
Дата 18.7.2011, 13:36 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 259
Регистрация: 11.12.2006
Где: Украина, Кривой Р ог

Репутация: 1
Всего: 4



Цитата(bsa @  17.7.2011,  16:00 Найти цитируемый пост)
Они нужны для унификации интерфейса доступа к разным объектам.

Совершенно верно, но приведу более понятный (с моей колокольни) пример.
Представь, что у тебя есть программа - примитивный графический редактор, котрый умеет только рисовать фигуры (Окружности, треугольники, кватраты и т.д.)

Алгоритм работы:
1. Пользователь из палитры выбирает фигуру, кидает на холст и задает параметры:
1.1 Общие для всех фигур: тип фигуры, позиция, цвет линий, цвет заливки;
1.2 Частные для фигуры конкретного типа: Окружность - диаметр окружности; Квадрат - длинна ребра квадрата.
2. Новая фигура добавляется в список фигур.
3. Вызывается процедура, которая перерисовывает холст (т.е. очищает и выводит все фигуры из списка).

Как это работает с полиморфизмом?
1. Объявляется базовый класс TShape, который содержит набор общих свойств(1.1) и список деклараций общих методов, которые помечены virtual и будут реализованы в потомках.
Например: Draw - нарисовать; Rotate - повернуть; Move - переместить.
Эти методы и являются виртуальными.
2. Объявляются классы-потомки от TShape, которые реализуют конкретную фигуру.
Например TSquare - квадрат; TCircle - окружность; TTriangle - треугольник.
В каждом потомке НЕОБХОДИМО реализовать все виртуальные методы родительского класса TShape (Draw, Rotate, Move, ...).
При этом реализация ориентируется на конкретный тип фигуры.
Например:
TCircle.Draw - нарисовать окружность
- окружность сама знает как отрисовываться относительно позиции фигуры (точка позиции совпадает с ценром фигуры.)
- огружность сама знает как заливаться цветом - заливка от центра
Square.Draw - нарисовать квадрат
- квадрат сам знает как отрисовываться относительно позиции фигуры (точка позиции совпадает с левым верхним углом  фигуры.)
- квадрат сам знает как заливаться цветом - заливка от центра, который вычисляется исходя из позиции фигуры и длинны стороны.
3. Созданые объекты добавляются в список объектов базового класса (TShape).
4. Вызывается процедура перерисовки холста (по таймеру, либо по событию).
Процедура перебирает все фигуры из списка и вызывает виртуальную функцию Draw.
В реальности будет вызвана последняя переотределенная функция объекта (Например, при наследовании "TShape << TRectangle << TSquare" будет вызвана TSquare.Draw несмотря на то, что в TRectangle тоже есть реализация Draw).

PS: Если словесное описание непонятно, могу выразиться в коде. Пиши, если что.

Это сообщение отредактировал(а) ZVano - 18.7.2011, 14:57


--------------------
НЕ ФЛУДИМ. Пользуемся кнопками "+" или "-" для выражения своего отношения к теме или сообщению.
Гуглим "Как правильно задавать вопросы"
PM MAIL Skype   Вверх
Hagrael
Дата 19.7.2011, 09:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 143
Регистрация: 26.6.2011

Репутация: нет
Всего: нет



Всем большое спасибо smile Значит, в C++ нету отдельного синтаксиса для создания интерфейса (как в PHP, к примеру), и интерфейс реализуется через класс посредством виртуальных функций. И выходит, что виртуальные функции говорят, что у этого класса функция должна реализовываться таким образом, как описывается в теле виртуальной функции, а у классов, наследующих этот класс, она должна реализовываться по-другому. Но почему не работает этот код? о_О
Код

#include <iostream>

class cShape {
    public:
    int a() {
        std::cout << "cShape";
    }
    int b() {
        a();
    }
};

class cTriangle : cShape {

};

int main() {
    cTriangle obj;
    obj.b();
}


Компилятор ворчит "error: `int cShape::b()' is inaccessible", но ведь этот метод public и не виртуальный! Причем ошибка относится к 8-й строчке (где объявляется метод b()), но появляется только при том, что присутствует строка obj.b(). Мистика  smile 

Это сообщение отредактировал(а) Hagrael - 19.7.2011, 09:03
PM MAIL   Вверх
azesmcar
Дата 19.7.2011, 09:34 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(Hagrael @  19.7.2011,  09:00 Найти цитируемый пост)
class cTriangle : cShape

Цитата

class cTriangle : public cShape


PM   Вверх
bsa
Дата 19.7.2011, 10:04 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Hagrael, по умолчанию классы наследуются с правом доступа private. Поэтому, если ты явно не укажешь другой, то из-вне методы предка будут недоступны. И вообще, причем тут виртуальные методы? У тебя их нет в примере!
Цитата(Hagrael @  19.7.2011,  09:00 Найти цитируемый пост)
И выходит, что виртуальные функции говорят, что у этого класса функция должна реализовываться таким образом, как описывается в теле виртуальной функции, а у классов, наследующих этот класс, она должна реализовываться по-другому. Но почему не работает этот код?
Виртуальные методы говорят, что их реализацию можно заменить другой в наследнике. А вот абстрактные методы (virtual int method() = 0;) необходимо заменить в потомке, экземпляр класса которого планируется уже создавать (создать объект абстрактного класса невозможно). Именно с помощью абстрактных методов делается интерфейс.
PM   Вверх
Hagrael
Дата 19.7.2011, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 143
Регистрация: 26.6.2011

Репутация: нет
Всего: нет



Все ясно! Спасибо, форумчане!
PM MAIL   Вверх
bsa
Дата 19.7.2011, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196




M
bsa
Hagrael, раз ответ на вопрос получен, то пометь тему решенной

PM   Вверх
Сыроежка
Дата 19.7.2011, 18:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 24.6.2011

Репутация: 1
Всего: 1



Цитата(Hagrael @  19.7.2011,  09:00 Найти цитируемый пост)
Всем большое спасибо smile Значит, в C++ нету отдельного синтаксиса для создания интерфейса (как в PHP, к примеру), и интерфейс реализуется через класс посредством виртуальных функций. И выходит, что виртуальные функции говорят, что у этого класса функция должна реализовываться таким образом, как описывается в теле виртуальной функции, а у классов, наследующих этот класс, она должна реализовываться по-другому. Но почему не работает этот код? о_О
Выделить всёкод C++
    
#include <iostream>
class cShape {
    public:
    int a() {
        std::cout << "cShape";
    }
    int b() {
        a();
    }
};
class cTriangle : cShape {
};
int main() {
    cTriangle obj;
    obj.b();
}


Компилятор ворчит "error: `int cShape::b()' is inaccessible", но ведь этот метод public и не виртуальный! Причем ошибка относится к 8-й строчке (где объявляется метод b()), но появляется только при том, что присутствует строка obj.b(). Мистика  smile 



У вас тут несколько ошибок в коде. Во первых, если вы определяете функцию, как возвращающее значение, отиличное от void, то вы должны на самом деле возвращать значение. То есть у вас функция b() объявлена, как возвращающая значение типа int, а на самом деле вы ничего не возвращаете.
Во-вторых, чтобы функция была виртуальной, нужно при ее объявлении в базовом классе использовать ключевое слово virtual.

В-третьих, производный класс у вас наследует базовый класс, как закрытый. В этом случае открытые функции базового класса становятся, если память не изменяет, закрытыми в производном классе. Поэтому вы не можете вызвать obj.b();
PM MAIL   Вверх
Hagrael
Дата 20.7.2011, 07:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 143
Регистрация: 26.6.2011

Репутация: нет
Всего: нет



Сыроежка, понятно smile Но с виртуальными функциями тут проблем не было, т. к. их самих не было smile Я экспериментировал с обычным наследованием  smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

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


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0580 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.