Виртуальная функция может быть переопределена в производном классе.
Чисто виртуальная функция должна быть переопределена в производном классе.
Чисто виртуальные функции обычно используют для создания интерфейсных классов.
Здравствуйте, MT, Вы писали:
MT>Чем отличается виртуальная функция от чистой виртуальной функции? MT>На примере двух классов:
MT>
MT>class Shape { virtual void draw(); }
// Здесь функция объявлена; предполагается, что ее определение - вне объявления класса.
// Отсутствие определения - вызовет ошибку линковки
// поскольку ссылка на функцию помещена в VMT этого класса
MT>class Shape2 { virtual void draw() = 0; }
// Эту функцию можно не определять (хотя можно и определить).
// А вот VMT с нуллевой ссылкой уже быть не может,
// поэтому создать экземпляр класса Shape2 невозможно
MT>
Наличие чисто виртуальной функции в твоем классе делает его абстрактным, объекты такого класса нельзя создавать, хотя можно объявить ссылки и указатели. Чисто виртуальная функция может иметь реализацию, только ее нельзя определить в классе.
Если умудриться вызвать такую функцию через ссылку или указатель, т.е. добиться вызова через втбл, то прога грохнется.
А еще очень много всего, но это лучше в книгах умных почитать или поиском пользоваться
Of course, the code must be complete enough to compile and link.
Re[2]: Virtual and Pure Virtual function
От:
Аноним
Дата:
25.08.03 13:33
Оценка:
Здравствуйте, Кодт, Вы писали:
MT>>
MT>>class Shape { virtual void draw(); }
К>// Здесь функция объявлена; предполагается, что ее определение - вне объявления класса.
К>// Отсутствие определения - вызовет ошибку линковки
К>// поскольку ссылка на функцию помещена в VMT этого класса
MT>>class Shape2 { virtual void draw() = 0; }
К>// Эту функцию можно не определять (хотя можно и определить).
К>// А вот VMT с нуллевой ссылкой уже быть не может,
Может, еще как может. Причем возможен даже вызов чисто виртуальной функции.
К>// поэтому создать экземпляр класса Shape2 невозможно
MT>>
Добавлю свои 2 копейки.
Ты можешь создать объект типа Shape, и не можешь — типа Shape2, потому как там чистая виртуальная функция. Получается абстрактный класс, как в Яве.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Но есть противоречивые ответы...
Поэтому уточните пожалуста — должен ли я определять чисто виртуальную функциу в производном классе, или можно не определять?
MT>Д. день!
MT>Чем отличается виртуальная функция от чистой виртуальной функции? MT>На примере двух классов:
MT>
Здравствуйте, Аноним, Вы писали:
MT>>>class Shape2 { virtual void draw() = 0; } К>>// Эту функцию можно не определять (хотя можно и определить). К>>// А вот VMT с нуллевой ссылкой уже быть не может,
А>Может, еще как может. Причем возможен даже вызов чисто виртуальной функции.
Это что за компилер такой?
VC6 — не создает!
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, MT, Вы писали:
MT>Но есть противоречивые ответы... MT>Поэтому уточните пожалуста — должен ли я определять чисто виртуальную функциу в производном классе, или можно не определять?
Если у тебя в классе есть чисто виртуальные функции, то класс является абстрактным; если в потомке абстрактного класса переопределены не все функции, являющиеся в классе-предке чисто виртуальными, то этот класс-потомок также абстрактный.
Класс не является абстрактным, только если в нем нет ни собственных ЧВФ, ни непереопределенных ЧВФ, "оставшихся в наследство" от класса-предка.
Это очень легко сделать. Деструктор абстрактной базы установит вптр на таблицу абстрактной базы,которая содержит некоторую заглушку. Вызови в деструкторе абстрактной базы функцию, которая вызывает чисто виртуальную функцию и ага.
Of course, the code must be complete enough to compile and link.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Это очень легко сделать. Деструктор абстрактной базы установит вптр на таблицу абстрактной базы,которая содержит некоторую заглушку. Вызови в деструкторе абстрактной базы функцию, которая вызывает чисто виртуальную функцию и ага.
Не, ну понятно, что обойти можно все, что угодно!
Мы-то говорим о стандартных средствах языка!
И вопрос так ставился изначально. А потом чел пишет вдруг, что у него создает.
Так пусть приведет, как стандарт обходит.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[4]: Virtual and Pure Virtual function
От:
Аноним
Дата:
25.08.03 13:56
Оценка:
Здравствуйте, LaptevVV, Вы писали:
А>>Может, еще как может. Причем возможен даже вызов чисто виртуальной функции. LVV>Это что за компилер такой? LVV>VC6 — не создает!
Создает.
class b;
void g(b*);
class b
{
public:
b()
{
g(this);
}
virtual void f() = 0;
};
class d : public b
{
public:
void f()
{}
};
void g(b* bb)
{
bb->f();
}
int main()
{
d dd; // Наслаждаемся эффектом!return 0;
}
Кодт говорит, что не может быть VMT с нулевой ссылкой, Аноним говорит, что может — т.е. для абстрактного класса создается VMT. Я согласен с Анонимом, и пример, который я привел, это показывает (по-моему)
Of course, the code must be complete enough to compile and link.
Re[4]: Virtual and Pure Virtual function
От:
Аноним
Дата:
25.08.03 14:05
Оценка:
Здравствуйте, LaptevVV, Вы писали:
LVV>VC6 — не создает!
Кстати, именно VC6 грешит тем, что позволяет создавать временные объекты абстрактных типов.
Здравствуйте, Аноним, Вы писали:
А>Создает. Пардон-с!!! Где ж тут создание есть создание объекта абстракного класса?
Смотри в коде комментарии А>
А>class b;
А>void g(b*);
А>class b
А>{
А>public:
А> b(){g(this);}
А> virtual void f() = 0; //чисто виртуальная
А>};
А>class d : public b //наследник
А>{
А>public:
А> void f(){} //а вот и реализация!!!!!
А>};
А>void g(b* bb)
А>{
bb->>f();
А>}
А>int main()
А>{
А> d dd; // Пардон!! Создали не из абстрактного класса
А> return 0;
А>}
А>
Ну и что, что тело пустое у функции в наследнике — это все равно реализация! Так что создал ты нормальный объект.
А в функции g у тебя не объект, а указатель на объект. А это можно.
А ты вызвал бы g и посмотрел, что получается.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Вы не о том. А о чем Аноним и лоренцо — смотри выше в моем примере. Кроме того, вижуал действительно позволяет создавать объект абстрактного класса (если я ничего не путаю) — тут как-то об этом говорили, может Аноним подробнее скажет
Of course, the code must be complete enough to compile and link.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Кодт говорит, что не может быть VMT с нулевой ссылкой, Аноним говорит, что может — т.е. для абстрактного класса создается VMT. Я согласен с Анонимом, и пример, который я привел, это показывает (по-моему)
Если б я реализовывал, то конечно создавал бы. Наследовать потом проще. Разве что указатели оставлять нулевые, подчеркивая абстрактность. Наверное, они так же рассуждали.
Но, уважаемый Lorenzo, поясните мне неучу, почему аноним считает (и приводит пример), что абстрактный объект создается.
Я откомеентарил — у него ж там все от наследника. Указатель в функции g — так указатель вроде не запрещается создавать даже на
class aaa;
aaa *p;
а уж у него вообще класс определен.
Что я непонимаю?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!