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

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

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

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

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

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

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

Программа состоит из 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
Ответы с готовыми решениями:

Вызов метода производного класса через указатель на базовый класс
Всем привет ! Подскажите почему , при выполнении строки 45 я получаю ошибку...

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

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

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

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

8
nmcf
6274 / 5577 / 2537
Регистрация: 14.04.2014
Сообщений: 23,468
16.06.2014, 16:25 2
Ну так она объявлена виртуальной в базовом, а во втором не переопределена.
1
Tulosba
:)
Эксперт С++
4749 / 3243 / 497
Регистрация: 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
6274 / 5577 / 2537
Регистрация: 14.04.2014
Сообщений: 23,468
16.06.2014, 19:18 5
Ты сначала создай то, что можно вызывать. В MyTriangle функции newArea() нет.
1
zss
Модератор
Эксперт С++
7178 / 6677 / 4226
Регистрация: 18.12.2011
Сообщений: 17,622
Завершенные тесты: 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
Комп_Оратор)
Эксперт по математике/физике
7053 / 3356 / 454
Регистрация: 04.12.2011
Сообщений: 9,332
Записей в блоге: 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...


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

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

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