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

Pure virtual function definition (C++11)

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

Author24 — интернет-сервис помощи студентам
Объясните мне, как ламеру, для чего может понадобится определение чисто виртуальной функции?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.03.2015, 21:38
Ответы с готовыми решениями:

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

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

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

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

11
Модератор
Эксперт С++
13636 / 10857 / 6452
Регистрация: 18.12.2011
Сообщений: 28,941
17.03.2015, 21:53 2
1. Для того, чтобы нельзя было создать экземпляр базового класса.
0
Неэпический
18093 / 10680 / 2060
Регистрация: 27.09.2012
Сообщений: 26,881
Записей в блоге: 1
17.03.2015, 21:53 3
Допустим, если у Вас есть вызов виртуальной функции в конструкторе
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  [ТС] 4
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Эксперт С++
8216 / 5046 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
17.03.2015, 23:47 5
Лучший ответ Сообщение было отмечено 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
Эксперт С++
8971 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
18.03.2015, 00:12 6
Цитата Сообщение от castaway Посмотреть сообщение
Объясните мне, как ламеру, для чего может понадобится определение чисто виртуальной функции?
например, если нужно сделать чисто-виртуальный диструктор.
0
13 / 13 / 2
Регистрация: 13.09.2013
Сообщений: 113
18.03.2015, 01:46 7
castaway, для того что бы реализовать интерфейс, что бы в конечном итоге минимизировать зависимости. При объявлении не pure vf вы будете вынуждены дать определение ф-и (а кому оно надо,если класс - чистый интерфейс?). Еще и еще раз : методы должны вызываться через интерфейс, только так можно достичь максимальной гибкости системы (аля паттерны gof).
0
Эксперт С++
8971 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
18.03.2015, 01:59 8
Цитата Сообщение от TheChosenOne Посмотреть сообщение
Еще и еще раз : методы должны вызываться через интерфейс, только так можно достичь максимальной гибкости системы (аля паттерны gof).
что тут у нас: ооп головного мозга?
0
Неэпический
18093 / 10680 / 2060
Регистрация: 27.09.2012
Сообщений: 26,881
Записей в блоге: 1
18.03.2015, 06:06 9
Цитата Сообщение от 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  [ТС] 10
Цитата Сообщение от hoggy Посмотреть сообщение
например, если нужно сделать чисто-виртуальный диструктор.
Можно поподробней?

Цитата Сообщение от TheChosenOne Посмотреть сообщение
castaway, для того что бы реализовать интерфейс, что бы в конечном итоге минимизировать зависимости. При объявлении не pure vf вы будете вынуждены дать определение ф-и (а кому оно надо,если класс - чистый интерфейс?). Еще и еще раз : методы должны вызываться через интерфейс, только так можно достичь максимальной гибкости системы (аля паттерны gof).
Вы, наверное, тоже не правильно поняли вопрос... или я ответ.
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
18.03.2015, 10:31 11
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Эксперт С++
8216 / 5046 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
18.03.2015, 14:36 12
Цитата Сообщение от Croessmah Посмотреть сообщение
Никак не пойму что Вы хотели показать этими примерами.
Примерами ничего. Я ссылки дал с подробным описанием проблемы. Программа соответствует стандарту, но её поведение может быть неочевидно. Я сам наступал на эти грабли (хотел инициализировать в конструкторе часть класса с помощью виртуальной функции), поэтому в курсе, что так делать нельзя. Но для многих читающих это может быть неочевидно.
По ссылкам выше подробнее.

Не по теме:

Мы на Вы? оО

1
18.03.2015, 14:36
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.03.2015, 14:36
Помогаю со студенческими работами здесь

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

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

Error: a function-definition is not allowed here before '{' token|
Всем привет. Вот переписал код из учебника под названием &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 =...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru