Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
Xaklex
0 / 0 / 0
Регистрация: 20.04.2014
Сообщений: 4
16.06.2014, 16:21     Вызов виртуальной функции через указатель на базовый класс #1
Всем привет! Помогите пожалуйста разобраться с вызовом виртуальной функции в программе.

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

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

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

Программа состоит из 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();
}
Программу писал мой однокурсник... Он тоже сдавал ее, преподаватель ее принял. А мне вот не повезло...
Очень надеюсь на Вашу помощь!
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.06.2014, 16:21     Вызов виртуальной функции через указатель на базовый класс
Посмотрите здесь:

C++ Создать абстрактный базовый класс с виртуальной функцией
вызов функции из массива, через указатель.) C++
C++ Указатель на базовый класс и на производный
Создание объекта через указатель на базовый абстрактный класс C++
C++ Возможно ли? Базовый класс с чисто виртуальной функцией и наследники
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
nmcf
4324 / 3745 / 1260
Регистрация: 14.04.2014
Сообщений: 14,685
16.06.2014, 16:25     Вызов виртуальной функции через указатель на базовый класс #2
Ну так она объявлена виртуальной в базовом, а во втором не переопределена.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
16.06.2014, 16:47     Вызов виртуальной функции через указатель на базовый класс #3
Цитата Сообщение от Xaklex Посмотреть сообщение
C++
1
2
3
MyTriangle tr;
//...
cout << "Площадь равна (Виртуальная функция) " << tr.newArea()
Вы, по-моему, вообще не понимаете для чего нужны виртуальные функции.
Для вызова виртуальной функции надо иметь указатель или ссылку на базовый класс, а так получается вызов, который заранее известен на момент компиляции.
Xaklex
0 / 0 / 0
Регистрация: 20.04.2014
Сообщений: 4
16.06.2014, 18:58  [ТС]     Вызов виртуальной функции через указатель на базовый класс #4
А как тогда можно в данной программе вызвать виртуальную функцию? Tulosba, Вы правы, с виртуальными функциями у меня туго... Но пытаюсь как могу разобраться.

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

zss, строку переделаю, но про вызов виртуальной функции:
C++
1
 cout << "Площадь равна (Виртуальная функция) " << tr->newArea() << endl;
Я говорил преподавателю о том, что это и есть вызов, на что он мне ответил: "Виртуальная функция вызывается только через указатель на базовый класс". Но все равно, спасибо за ответ)
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6173 / 2902 / 284
Регистрация: 04.12.2011
Сообщений: 7,729
Записей в блоге: 3
17.06.2014, 04:17     Вызов виртуальной функции через указатель на базовый класс #8
Цитата Сообщение от Xaklex Посмотреть сообщение
Я говорил преподавателю о том, что это и есть вызов, на что он мне ответил: "Виртуальная функция вызывается только через указатель на базовый класс".
И все дружно это подтверждают. zss, показывает как создать объект с доступом через указатель и потом через указатель же и вызвать метод. Причем указатель базового класса инициализируется адресом объекта производного класса. Повторите указатели и потом перечитайте наследование иначе будете "всё равно спасибо" ещё долго говорить.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.06.2014, 14:36     Вызов виртуальной функции через указатель на базовый класс
Еще ссылки по теме:

C++ Создайте базовый абстрактный класс «Товар» с чистой виртуальной функцией вывода данных
Создать абстрактный базовый класс Number с виртуальной функцией - норма C++
Вызов метода производного класса через указатель на базовый класс C++

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

Или воспользуйтесь поиском по форуму:
Xaklex
0 / 0 / 0
Регистрация: 20.04.2014
Сообщений: 4
18.06.2014, 14:36  [ТС]     Вызов виртуальной функции через указатель на базовый класс #9
IGPIGP, я всегда благодарен даже просто тому, что мне ответили С программой я разобрался, преподаватель подсказал мне все-таки еще немного (достал я его). Программирование мне нравится, с предыдущими темами разобрался без особой сложности. Но вот с виртуальными функциями почему-то возникли затруднения... Сейчас уже все позади Думаю, в будущем с виртуальными функциями придется сталкивать не раз. Поэтому буду углубляться в эту тему дальше. А то "бегать" от данного метода не горю желанием) И еще раз говорю всем, кто ответил мне, огромное спасибо за отзывчивость и ответы на простом, доступном языке
Yandex
Объявления
18.06.2014, 14:36     Вызов виртуальной функции через указатель на базовый класс
Ответ Создать тему
Опции темы

Текущее время: 23:30. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru