Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10

Pure virtual function definition (C++11)

17.03.2015, 21:38. Показов 5268. Ответов 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
13761 / 10957 / 6488
Регистрация: 18.12.2011
Сообщений: 29,219
17.03.2015, 21:53
1. Для того, чтобы нельзя было создать экземпляр базового класса.
0
Неэпический
 Аватар для Croessmah
18131 / 10715 / 2064
Регистрация: 27.09.2012
Сообщений: 27,008
Записей в блоге: 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,169
Записей в блоге: 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
18131 / 10715 / 2064
Регистрация: 27.09.2012
Сообщений: 27,008
Записей в блоге: 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,169
Записей в блоге: 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
Ответ Создать тему
Опции темы

Новые блоги и статьи
Тестирование энергоэффективности и скорости вычислений видеокарт в BOINC проектах
Programma_Boinc 08.07.2025
Тестирование энергоэффективности и скорости вычислений видеокарт в BOINC проектах Опубликовано: 07. 07. 2025 Рубрика: Uncategorized Автор: AlexA Статья размещается на сайте с разрешения. . .
Раскрываем внутренние механики Android с помощью контекста и манифеста
mobDevWorks 07.07.2025
Каждый Android-разработчик сталкивается с Context и манифестом буквально в первый день работы. Но много ли мы задумываемся о том, что скрывается за этими обыденными элементами? Я, честно говоря,. . .
API на базе FastAPI с Python за пару минут
AI_Generated 07.07.2025
FastAPI - это относительно молодой фреймворк для создания веб-API, который за короткое время заработал бешеную популярность в Python-сообществе. И не зря. Я помню, как впервые запустил приложение на. . .
Основы WebGL. Раскрашивание вершин с помощью VBO
8Observer8 05.07.2025
На русском https:/ / vkvideo. ru/ video-231374465_456239020 На английском https:/ / www. youtube. com/ watch?v=oskqtCrWns0 Исходники примера:
Мониторинг микросервисов с OpenTelemetry в Kubernetes
Mr. Docker 04.07.2025
Проблема наблюдаемости (observability) в Kubernetes - это не просто вопрос сбора логов или метрик. Это целый комплекс вызовов, которые возникают из-за самой природы контейнеризации и оркестрации. К. . .
Проблемы с Kotlin и Wasm при создании игры
GameUnited 03.07.2025
В современном мире разработки игр выбор технологии - это зачастую балансирование между удобством разработки, переносимостью и производительностью. Когда я решил создать свою первую веб-игру, мой. . .
Создаем микросервисы с Go и Kubernetes
golander 02.07.2025
Когда я только начинал с микросервисами, все спорили о том, какой язык юзать. Сейчас Go (или Golang) фактически захватил эту нишу. И вот почему этот язык настолько заходит для этих задач: . . .
C++23, квантовые вычисления и взаимодействие с Q#
bytestream 02.07.2025
Я всегда с некоторым скептицизмом относился к громким заявлениям о революциях в IT, но квантовые вычисления - это тот случай, когда революция действительно происходит прямо у нас на глазах. Последние. . .
Вот в чем сила LM.
Hrethgir 02.07.2025
как на английском будет “обслуживание“ Слово «обслуживание» на английском языке может переводиться несколькими способами в зависимости от контекста: * **Service** — самый распространённый. . .
Использование Keycloak со Spring Boot и интеграция Identity Provider
Javaican 01.07.2025
Два года назад я получил задачу, которая сначала показалась тривиальной: интегрировать корпоративную аутентификацию в микросервисную архитектуру. На тот момент у нас было семь Spring Boot приложений,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru