Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/25: Рейтинг темы: голосов - 25, средняя оценка - 4.80
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10

Pure virtual function definition (C++11)

17.03.2015, 21:38. Показов 5508. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Объясните мне, как ламеру, для чего может понадобится определение чисто виртуальной функции?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.03.2015, 21:38
Ответы с готовыми решениями:

R6025 pure virtual function call
Ошибка - r6025 pure virtual function call. Что не так? #include <iostream> #include <cstring> using namespace std; class...

Pure virtual function call (не видит переопределенный метод)
Здравствуйте. Имеется базовый класс Cars и унаследованные от него классы Jeep, Hatchback, Sedan //Cars.h class Cars { public: ...

R6025 pure virtual function call при вызове метода, реализованного в дочернем классе
Всем привет. Вот такая ошибка у меня возникает при вызове метода, который реализован в дочернем классе, но потом он почему-то становится...

11
Модератор
Эксперт С++
 Аватар для zss
13773 / 10966 / 6491
Регистрация: 18.12.2011
Сообщений: 29,243
17.03.2015, 21:53
1. Для того, чтобы нельзя было создать экземпляр базового класса.
0
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
17.03.2015, 21:53
Допустим, если у Вас есть вызов виртуальной функции в конструкторе
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
 
class abstract
{
public:
    abstract() { foo() ; }
    virtual void foo() const = 0 ;
};
 
void abstract::foo () const { 
    std::cout << "abstract" << std::endl ; 
}
 
 
class child : public abstract
{
    void foo() const { std::cout << "child" << std::endl ; }
};
 
int main() {
    child x ;
}
без определения получим неопределенный символ
2
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
17.03.2015, 22:44  [ТС]
zss, Вы не правильно поняли суть вопроса.

Croessmah, как вариант сойдёт. Правда GCC ругается:
Bash
1
2
3
4
main.cpp: In constructor 'abstract::abstract()':
main.cpp:6:22: warning: pure virtual 'virtual void abstract::foo() const' called from constructor
     abstract() { foo() ; }
                      ^
Т.е. по мнению компилятора это не нормально. Да и мне кажется, что можно обойтись без этого.

Внесу некоторую ясность.
declaration - объявление:
C++
1
    virtual void foo() const = 0;
definition - определение:
C++
1
2
3
void abstract::foo() const {
    std::cout << "abstract" << std::endl;
}
До сего дня я не знал, что чисто виртуальную функцию можно определить (стыд и срам мне).
По этому мне стало интересно, для чего это может понадобится и в каких случаях пригодиться.
1
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
17.03.2015, 23:47
Лучший ответ Сообщение было отмечено Ilot как решение

Решение

Цитата Сообщение от castaway Посмотреть сообщение
До сего дня я не знал, что чисто виртуальную функцию можно определить (стыд и срам мне).
По этому мне стало интересно, для чего это может понадобится и в каких случаях пригодиться.
Для чего может понадобиться чисто виртуальная функция объяснять не буду - думаю знаешь. А вот её реализацию можно сделать чтобы задать дефолтное поведение. То есть не хотим реализовывать - вызываем базовую. Вот кстати пример, как можно её вызвать напрямую.
C++
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
 
// абстрактный класс
class Shape
{
    public:
        // чисто виртуальная функция имеет реализацию. Фигура может быть нарисована
        // ошибка, нельзя иметь реализацию внутри класса
        //virtual void draw() const = 0 { std::cout << "Draw Shape\n"; }
        // объявляем прототип чисто виртуальной функции
        virtual void draw() const = 0;
        virtual ~Shape(){}
};
 
// реализация чисто виртуальной функции. Все легально
void Shape::draw() const
{
    std::cout << "Draw Shape\n";
}
 
// наследуемся от класса-протокола Shape. Треугольник является фигурой
// наследуется интерфейс функции draw.
class Triangle : public Shape
{
    public:
        // переобределяем метод draw() const. Треугольник рисуется по другому
        virtual void draw() const { std::cout << "Draw Triangle\n"; }
        virtual ~Triangle(){}
};
 
// Прямоугольный треугольник является треугольником.
// наследуется интерфейс и реализация по-умолчанию функции draw
class RightTriangle : public Triangle
{
    public:
        // переобределяем метод draw() const. Прямоугольный треугольник рисуется по другому
        void draw() const { std::cout << "Draw Right Triangle\n"; }
};
 
int main()
{
    //Shape *ps = new Shape;        // ошибка - класс абстрактный
    Shape *ps1 = new Triangle;      // хорошо
    ps1->draw();                    // вызовется метод Triangle::draw() const
    Shape *ps2 = new RightTriangle; // хорошо
    ps2->draw();                    // вызовется метод RightTriangle::draw() const
    ps1->Shape::draw();             // вызовется метод Shape::draw() const
    //ps2->Triangle::draw();        // ошибка, Triangle является базовым классом
                                    // RightTriangle, но не Shape
    RightTriangle rt;
    rt.Triangle::draw();            // вызовется метод Triangle::draw() const
    rt.draw();                      // вызовется метод RightTriangle::draw() const
}
Цитата Сообщение от Croessmah Посмотреть сообщение
если у Вас есть вызов виртуальной функции в конструкторе
А вот это уже грозит бедами и вырванными волосами на чьей-то голове. Надо помнить, что механизм переопределения функций ещё не был вызван.
http://stackoverflow.com/quest... onstructor
http://stackoverflow.com/quest... l-function

Добавлено через 8 минут
Цитата Сообщение от MrGluck Посмотреть сообщение
А вот её реализацию можно сделать чтобы задать дефолтное поведение.
У нас в проекте достаточно часто это используется - есть набор абстрактных методов, которые ты просто обязан реализовать или явно указать, что хочешь дефолтное поведение.
C++
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
#include <iostream>
 
class Maker
{
public:
    virtual void make() = 0;
    virtual ~Maker() = default;
};
 
void Maker::make() { std::cout << "Maker::make\n"; }
 
class LazyMaker : public Maker
{
public:
    // I don't want make my job! Please, smb make it for me..
    void make() override { Maker::make(); }
};
 
 
int main()
{
    LazyMaker dm;
    dm.make();
    std::cin.get();
}
Добавлено через 4 минуты
Также бывает, что в чисто виртуальной функции лежат какие-то общие алгоритмы работы, но для каждого производного класса они не полностью описывают необходимый алгоритм.
4
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
18.03.2015, 00:12
Цитата Сообщение от castaway Посмотреть сообщение
Объясните мне, как ламеру, для чего может понадобится определение чисто виртуальной функции?
например, если нужно сделать чисто-виртуальный диструктор.
0
13 / 13 / 2
Регистрация: 13.09.2013
Сообщений: 113
18.03.2015, 01:46
castaway, для того что бы реализовать интерфейс, что бы в конечном итоге минимизировать зависимости. При объявлении не pure vf вы будете вынуждены дать определение ф-и (а кому оно надо,если класс - чистый интерфейс?). Еще и еще раз : методы должны вызываться через интерфейс, только так можно достичь максимальной гибкости системы (аля паттерны gof).
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
18.03.2015, 01:59
Цитата Сообщение от TheChosenOne Посмотреть сообщение
Еще и еще раз : методы должны вызываться через интерфейс, только так можно достичь максимальной гибкости системы (аля паттерны gof).
что тут у нас: ооп головного мозга?
0
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
18.03.2015, 06:06
Цитата Сообщение от MrGluck Посмотреть сообщение
А вот это уже грозит бедами и вырванными волосами на чьей-то голове
Никак не пойму что Вы хотели показать этими примерами.
Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
18.03.2015, 09:39  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
например, если нужно сделать чисто-виртуальный диструктор.
Можно поподробней?

Цитата Сообщение от TheChosenOne Посмотреть сообщение
castaway, для того что бы реализовать интерфейс, что бы в конечном итоге минимизировать зависимости. При объявлении не pure vf вы будете вынуждены дать определение ф-и (а кому оно надо,если класс - чистый интерфейс?). Еще и еще раз : методы должны вызываться через интерфейс, только так можно достичь максимальной гибкости системы (аля паттерны gof).
Вы, наверное, тоже не правильно поняли вопрос... или я ответ.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
18.03.2015, 10:31
castaway, Ну синтетический пример.
Данный код работать не будет.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A
{
public:
   virtual ~A() = 0;
};
 
class B : public A
{
public:
   ~B() {}
};
 
int main()
{
   A* b = new B;
   delete b;
}
А данный будет.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A
{
public:
   virtual ~A() = 0;
};
 
A::~A() {}
 
class B : public A
{
public:
   ~B() {}
};
 
int main()
{
   A* b = new B;
   delete b;
}
Добавлено через 1 минуту
Причина: N3376 12.4/9
A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any
derived class are created in the program, the destructor shall be defined.
1
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
18.03.2015, 14:36
Цитата Сообщение от Croessmah Посмотреть сообщение
Никак не пойму что Вы хотели показать этими примерами.
Примерами ничего. Я ссылки дал с подробным описанием проблемы. Программа соответствует стандарту, но её поведение может быть неочевидно. Я сам наступал на эти грабли (хотел инициализировать в конструкторе часть класса с помощью виртуальной функции), поэтому в курсе, что так делать нельзя. Но для многих читающих это может быть неочевидно.
По ссылкам выше подробнее.

Не по теме:

Мы на Вы? оО

1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
18.03.2015, 14:36
Помогаю со студенческими работами здесь

Protected abstract virtual base pure virtual private destructor
Хай, all) Вопрос не для начинающих и дурацкий) В разделе для экспертов публиковать не стал, чтобы не засорять его) Наткнулся тут на...

В дочерних классах компилятор сообщает об Undefined reference to pure virtual functions
Здравствуйте! Имеется базовый класс с чисто виртуальным деструктором (virtual ~Service() = 0). Однако в дочерних классах мне...

A function-definition is not allowed here before
Здравствуйте! Скажите пожалуйста, где здесь ошибка в написании кода (синтаксиса): #include &lt;iostream&gt; using namespace...

Error: a function-definition is not allowed here before '{' token|
Всем привет. Вот переписал код из учебника под названием &quot;Дирк Хенкеманс и Марк Ли программирование на c++&quot;. Код из игры под...

Error: a function-definition is not allowed here before '{' token|
#include &lt;iostream&gt; #include &lt;string&gt; char board = {}; void clearscreen(){ for(int i = 0;i&lt;24;i++){ ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru