Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Xaklex
0 / 0 / 0
Регистрация: 20.04.2014
Сообщений: 4
#1

Вызов виртуальной функции через указатель на базовый класс - C++

16.06.2014, 16:21. Просмотров 1000. Ответов 8
Метки нет (Все метки)

Всем привет! Помогите пожалуйста разобраться с вызовом виртуальной функции в программе.

В моей программе требуется организовать класс треугольник, определенный по длинам трех сторон содержащий методы нахождения периметра и площади (по формуле Герона).

http://www.cyberforum.ru/cpp-beginners/thread1501303.html
А так же определить виртуальную функцию для нахождения площади таким образом, чтобы в базовом и производном классе тела функций определялись по-разному.

Когда сдавал программу, преподаватель сказал, что не видит объявления виртуальной функции в программе. И сказал, что виртуальная функция вызывается только через указатель на базовый класс.

Программа состоит из 3-х файлов, помогите пожалуйста разобраться с объявлением виртуальной функции:

main:
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
54
55
56
57
58
59
60
61
#include "MyTriangle.cpp"
#include <iostream>
#include <windows.h>
using namespace std;
 
MyTriangle enter(){
    
    float x1, x2, x3; 
    cout << "Введите длину стороны A" << endl; 
    cin >> x1;
    cout << "Введите длину стороны B" << endl; 
    cin >> x2;  
    cout << "Введите длину стороны C" << endl; 
    cin >> x3;
    return MyTriangle(x1, x2, x3);
} 
 
void func() {
    MyTriangle tr;
    int number; 
    cout << "Введите данные треугольника " << endl;
    tr = enter();  
    cout << endl;
    cout << "1 Площадь по формуле Герона" << endl;
    cout << "2 Периметр " << endl;
    cout << "3 Высота " << endl;
    cout << "4 Площадь по высоте и основанию (Виртуальная функция)" << endl;
    cout << "5 Углы треугольника " << endl;
    cout << "6 Полное описание треугольника " << endl;
    cout << "Выберите что вы хотите сделать ваш вариант " << endl; 
    cin >> number; 
 
    switch(number) { 
        case 1: cout << "Площадь равна " << tr.newArea() << endl; break; 
        case 2: cout << "Периметр равен " << tr.perimetr() << endl; break; 
        case 3: cout << "Высота равна " << tr.height() << endl; break;
        case 4: cout << "Площадь по высоте и основанию равна " << tr.areaIsHeight() << endl; break; 
        case 5: tr.angle1(); break;
        case 6: cout << "Площадь равна (Виртуальная функция) " << tr.newArea() << endl;
         cout << "Периметр равен " << tr.perimetr() << endl;
         cout << "Высота равна " << tr.height() << endl;
         cout << "Площадь равна (формула Герона)  " << tr.areaIsHeight() << endl;
         tr.angle1(); break; 
        default: cout << "Не корректный ввод данных " << endl; break;
    }
}    
int main() {   
    setlocale(0, "rus"); 
    int k;
    cout << "1.Вводить данные" << endl;
    cout << "2.Выйти из программы" << endl;
    while(true){
        cout << "Введите номер операции" << endl; 
        cin >> k;
        switch(k) {
            case 1 : system("cls"); func(); break;
            case 2 : exit(EXIT_SUCCESS); break;
            default : cout << "Некорректный ввод данных" << endl;
        }
    }   
}
Triangle:
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
#include <iostream>
#include <cmath>
 
using namespace std;
 
class Triangle { 
    private: 
        float x1, x2, x3; 
        
    public: 
        Triangle() {}
        Triangle(float, float, float);
        ~Triangle() {}
        float perimetr(); 
        float height();
        float area2();
        void angle();
    const virtual float newArea() const {
        float p2 = (x1 + x2 + x3) / 2;
        float height = (2 * sqrt(p2 * (p2 - x1) * (p2 - x2) * (p2 - x3))) / x1;
        return 0.5 * x1 * height;
    }
}; 
 
Triangle::Triangle(float x1, float x2, float x3){
    this->x1 = x1;
    this->x2 = x2;
    this->x3 = x3; 
}
         
float Triangle :: area2() {
    float p2 = perimetr()/2;
    return sqrt(p2 * (p2 - x1) * (p2 - x2) * (p2 - x3));
} 
 
float Triangle :: perimetr() {
    return x1 + x2 + x3;  
} 
 
float Triangle :: height() { 
    float p2 = perimetr() / 2;
    return (2 * area2()) / x1;
}
 
void Triangle :: angle() {
    float A = (acos(cos((pow(x3, 2) + pow(x2, 2) - pow(x1, 2)) / (2 * x2 * x3))) * 180) / 3.14;
    float B = (acos(cos((pow(x1, 2) + pow(x3, 2) - pow(x2, 2)) / (2 * x1 * x3))) * 180) / 3.14;
    float C = 180 - (A + B);
    cout << "Угол А = " << A << " Угол В = " << B << " Угол С = " << C << endl;
}
MyTriangle:
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 "Triangle.cpp"
 
class MyTriangle : public Triangle {
    public:
        MyTriangle() : Triangle() {}
        MyTriangle(float x1, float x2, float x3) :
            Triangle(x1, x2, x3) {}
        float areaIsHeight();
        float height1();
        void angle1();
};
 
float MyTriangle :: areaIsHeight() {
    return area2();
}
 
float MyTriangle :: height1() {
    return height();
}
 
void MyTriangle :: angle1() {
    angle();
}
Программу писал мой однокурсник... Он тоже сдавал ее, преподаватель ее принял. А мне вот не повезло...
Очень надеюсь на Вашу помощь!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.06.2014, 16:21
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Вызов виртуальной функции через указатель на базовый класс (C++):

Указатель на базовый класс и дружественные функции
Здравствуйте. У меня есть базовый класс Number-простое целое число типа long...

Создание объекта через указатель на базовый абстрактный класс
Есть абстрактный класс, от него наследуется 3 класса. В программе предусмотрено...

Передача в контейнер объекта через указатель на базовый класс
Передаю в stl контейнер list указатель на производный класс, предварительно...

Возможно ли вызвать метод наследника через указатель на базовый класс
Возможно ли вызвать метод наследника,через указатель на базовый класс, если он...

Преобразование типа при вызове виртуального метода через указатель на базовый класс
Доброго времени суток. Наткнулся на вот такой вопрос в сети и пока что не смог...

8
nmcf
6237 / 5549 / 2524
Регистрация: 14.04.2014
Сообщений: 23,331
16.06.2014, 16:25 #2
Ну так она объявлена виртуальной в базовом, а во втором не переопределена.
1
Tulosba
:)
Эксперт С++
4746 / 3240 / 496
Регистрация: 19.02.2013
Сообщений: 9,046
16.06.2014, 16:47 #3
Цитата Сообщение от Xaklex Посмотреть сообщение
C++
1
2
3
MyTriangle tr;
//...
cout << "Площадь равна (Виртуальная функция) " << tr.newArea()
Вы, по-моему, вообще не понимаете для чего нужны виртуальные функции.
Для вызова виртуальной функции надо иметь указатель или ссылку на базовый класс, а так получается вызов, который заранее известен на момент компиляции.
2
Xaklex
0 / 0 / 0
Регистрация: 20.04.2014
Сообщений: 4
16.06.2014, 18:58  [ТС] #4
А как тогда можно в данной программе вызвать виртуальную функцию? Tulosba, Вы правы, с виртуальными функциями у меня туго... Но пытаюсь как могу разобраться.

Возможно, программу нужно как-то подкорректировать, чтобы она содержала вызов виртуальной функции? Если это возможно, подскажите пожалуйста, каким образом? Заранее спасибо)
0
nmcf
6237 / 5549 / 2524
Регистрация: 14.04.2014
Сообщений: 23,331
16.06.2014, 19:18 #5
Ты сначала создай то, что можно вызывать. В MyTriangle функции newArea() нет.
1
zss
Модератор
Эксперт С++
6952 / 6514 / 4135
Регистрация: 18.12.2011
Сообщений: 17,179
Завершенные тесты: 1
16.06.2014, 19:25 #6
Цитата Сообщение от Xaklex Посмотреть сообщение
MyTriangle tr;
Вместо этого надо
C++
1
Triangle* tr=new MyTriangle;
Вызов виртуальной функции:
C++
1
 cout << "Площадь равна (Виртуальная функция) " << tr->newArea() << endl;
1
Xaklex
0 / 0 / 0
Регистрация: 20.04.2014
Сообщений: 4
17.06.2014, 03:39  [ТС] #7
nmcf, хорошо, попробую добавить виртуальную функцию в MyTriangle, спасибо)

zss, строку переделаю, но про вызов виртуальной функции:
C++
1
 cout << "Площадь равна (Виртуальная функция) " << tr->newArea() << endl;
Я говорил преподавателю о том, что это и есть вызов, на что он мне ответил: "Виртуальная функция вызывается только через указатель на базовый класс". Но все равно, спасибо за ответ)
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7002 / 3295 / 448
Регистрация: 04.12.2011
Сообщений: 9,114
Записей в блоге: 5
17.06.2014, 04:17 #8
Цитата Сообщение от Xaklex Посмотреть сообщение
Я говорил преподавателю о том, что это и есть вызов, на что он мне ответил: "Виртуальная функция вызывается только через указатель на базовый класс".
И все дружно это подтверждают. zss, показывает как создать объект с доступом через указатель и потом через указатель же и вызвать метод. Причем указатель базового класса инициализируется адресом объекта производного класса. Повторите указатели и потом перечитайте наследование иначе будете "всё равно спасибо" ещё долго говорить.
1
Xaklex
0 / 0 / 0
Регистрация: 20.04.2014
Сообщений: 4
18.06.2014, 14:36  [ТС] #9
IGPIGP, я всегда благодарен даже просто тому, что мне ответили С программой я разобрался, преподаватель подсказал мне все-таки еще немного (достал я его). Программирование мне нравится, с предыдущими темами разобрался без особой сложности. Но вот с виртуальными функциями почему-то возникли затруднения... Сейчас уже все позади Думаю, в будущем с виртуальными функциями придется сталкивать не раз. Поэтому буду углубляться в эту тему дальше. А то "бегать" от данного метода не горю желанием) И еще раз говорю всем, кто ответил мне, огромное спасибо за отзывчивость и ответы на простом, доступном языке
0
18.06.2014, 14:36
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.06.2014, 14:36
Привет! Вот еще темы с решениями:

Вызов родовой функции (нужно передать массив в качестве аргумента функции через указатель)
#include &lt;iostream&gt; using namespace std; template &lt;class T1&gt; class mas { ...

Вызов функции из массива, через указатель
имею код #include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;utility&gt; using...

Создать абстрактный базовый класс с виртуальной функцией
Создать абстрактный базовый класс с виртуальной функцией – значением функций в...

Возможно ли? Базовый класс с чисто виртуальной функцией и наследники
есть такая ситуация, есть базовый класс и от него 2 наследника. У наследников...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru