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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> почему у виртуальной ф-ии должно быть пустое тело? 
V
    Опции темы
mrgloom
Дата 8.5.2014, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



ожидание 

Код

class A 
{
public:
    virtual void vf();
};
 
class B : public A
{
public:
    void vf()
    {
        printf("B::vf\n");
    }
};
 
int main() 
{
    A a;
    B b;
    b.vf();
     
    A* pa= &a;
    A* pb= &b;
    pa->vf();
    pb->vf();
    return 0;
}


получаю ошибку 

prog.cpp:(.text.startup+0x14): undefined reference to `vtable for A'
prog.cpp:(.text.startup+0x2d): undefined reference to `A::vf()'

https://ideone.com/MFvAdP


так работает 

Код

class A 
{
public:
    virtual void vf()
    {}
};
 
class B : public A
{
public:
    void vf()
    {
        printf("B::vf\n");
    }
};
 
int main() 
{
    A a;
    B b;
    b.vf();
     
    A* pa= &a;
    A* pb= &b;
    pa->vf();
    pb->vf();
    return 0;
}


https://ideone.com/NXV8tl



по почему по логике виртуальная ф-ия должна быть определена в базовом классе?

по идее если не определена, то

это рушить программу
    
Код

pa->vf();


это ок
    
Код

pb->vf();



причем без вызова ф-ии компилируется

Код

A* pa= &a;
A* pb= &b;
//pa->vf();
//pb->vf();


https://ideone.com/dogCao


понятно что можно было бы написать 

Код

virtual void vf()=0;


и это бы еще запретило создавать экземпляр класса А чтобы не вызвать ф-ию A.vf() которой нет.
https://ideone.com/aXSHAD


Это сообщение отредактировал(а) mrgloom - 8.5.2014, 14:21
PM MAIL   Вверх
vinter
Дата 8.5.2014, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


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

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



mrgloom, моя твоя не понимать. Ты что хотел, то? Взял, написал объявление функции, без определения, и чего-то ждёшь? Конечно оно не будет работать. vtable для A не может быть создана, т.к. в vtable помещается указатель на реализацию каждой virtual функции.  А ты функцию не реализовал!

Это сообщение отредактировал(а) vinter - 8.5.2014, 17:15


--------------------
Мой блог
PM MAIL WWW   Вверх
bsa
Дата 8.5.2014, 20:22 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



mrgloom, у тебя есть гарантия, что ты можешь вызвать любую виртуальную функцию любого объект класса, их имеющего. Чтобы это выполнялось есть три пути:
1. не дать тебе создать объект класса, у которого тело виртуальной функции не определено
2. не дать тебе скомпилировать код, в котором есть объявленные, но не реализованные виртуальные методы.
3. прерывать работу программы, которая пытается вызвать нереализованные виртуальные методы

Все эти варианты поддерживаются языком С++. Для первого варианта используются чисто виртуальные (абстрактные) методы. Со вторым вариантом ты уже столкнулся. Третий вариант может быть реализован как "последний рубеж защиты", если два предыдущих не отработали или сбой в программе.

Думаю, тебя интересует первый вариант. Это делается так:
Код
class MyClass
{
public:
...
    virtual ~MyClass(); //у класса с виртуальными методами обязан быть виртуальный деструктор
...
    virtual void pureVirtual() = 0; //вот это чисто виртуальный метод, его можно не реализовывать, но объект этого класса создать невозможно
                //только потомка, у которого перериализован этот метод
...
};

PM   Вверх
Lukkoye
Дата 8.5.2014, 21:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(mrgloom @  8.5.2014,  14:20 Найти цитируемый пост)
по почему по логике виртуальная ф-ия должна быть определена в базовом классе?


Потому что виртуальная функция - это та же самая обычная функция.

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

(важно понимать, что виртуальная функция в базовом классе, и в наследнике - это две принципиально разные функции, которые существуют в классе одновременно,  и могут быть вызваны отдельно друг от друга).

Если же вы не планируете вызывать её, и она нужна вам лишь для задания интерфейса, то вы можете сообщить компилятору о своем желании, создав "чисто-виртуальнцю функцию".







PM MAIL   Вверх
mrgloom
Дата 12.5.2014, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



bsa вся написал правильно и логично.
лучше всего в этом случае использовать pure virtual function

но смущает только 3 вариант когда класс объявлен с ошибкой и экземпляр его можно даже объявить и это не приводит к ошибке компиляции.
https://ideone.com/qCyWat

хотя это от компилятора наверно зависит.

т.к. тут не компилируется
http://www.compileonline.com/compile_cpp11_online.php

Это сообщение отредактировал(а) mrgloom - 12.5.2014, 15:25
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

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


 




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


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

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