Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
55 / 55 / 6
Регистрация: 07.07.2013
Сообщений: 345
1

Указатель на базовый класс и на производный

17.07.2013, 15:38. Просмотров 1523. Ответов 13
Метки нет (Все метки)

Пытаюсь разобраться с классами и наследованием.
Сама эта задача из Дейтела "Как программировать на C++"
Есть базовый класс Точка и у него один наследник Круг. В самой программе определяю две переменных у два указателя на эти классы.

Вообщем, если указателю на производный класс присвоить указатель на базовый, то странный вывод. Печатает что радиус равен 0 (я в комментарии показал вывод программы)

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include "iostream"
#include "iomanip"
 
class CPoint
{
    friend std::ostream &operator<<(std::ostream &out, const CPoint &point);
 
public:
    CPoint(double x=0.0, double y=0.0);
    void SetPoint(double x, double y);
 
protected:
    double mX, mY;
};
 
class CCircle : public CPoint
{
    friend std::ostream &operator<<(std::ostream &out, const CCircle &circle);
 
public:
    CCircle(double x=0.0, double y=0.0, double radius=1.0);
    void SetRadius(double radius);
 
protected:
    double mRadius;
};
 
 
 
 
 // CPoint
CPoint::CPoint(double x, double y)          { SetPoint(x, y); }
 
void CPoint::SetPoint(double x, double y)   { mX=x;  mY=y; }
 
std::ostream &operator<<(std::ostream &out, const CPoint &point)
{
    std::streamsize prec = std::cout.precision();
    out << "[" << std::fixed << std::setprecision(2) << point.mX << ", " << point.mY << "]" << std::setprecision(prec);
    return out;
}
 
 
 
 
 
// CCircle
CCircle::CCircle(double x, double y, double radius)
    : CPoint(x, y)
{
    SetRadius(radius);
}
 
void CCircle::SetRadius(double radius)          { mRadius=(radius>0.0) ? radius : 1.0; }
 
std::ostream &operator<<(std::ostream &out, const CCircle &circle)
{
    std::streamsize prec = std::cout.precision();
    out << "Центр = [" << std::fixed << std::setprecision(2) << circle.mX << ", " << circle.mY << "]; Радиус = " << circle.mRadius << std::setprecision(prec);
    return out;
}
 
 
 
 
 
 
int main()
{
    setlocale(LC_ALL, "Russian");
 
    CPoint      point(1.1, 2.2),  *ptrPoint;
    CCircle     circle(5.5, 6.6, 10.0),  *ptrCircle;
 
    ptrPoint=&point;
    ptrCircle=(CCircle *)ptrPoint;
    std::cout << "*ptrPoint:  " << *ptrPoint << std::endl;      // *ptrPoint:  [1.10, 2.20]
    std::cout << "*ptrCircle: " << *ptrCircle << std::endl;     // *ptrCircle: Центр = [1.10, 2.20]; Радиус = 0.00
 
    system("pause");
    return 0;
}

Почему второй вывод печатает Радиус = 0.00 ? Почему не мусор? Ведь у точки нет радиуса
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.07.2013, 15:38
Ответы с готовыми решениями:

Есть производный класс и базовый; при чём производный использует только ЧАСТЬ ресурсов базового, правильно ли это?
Ну то есть базовый класс A, с полями, допустим, a, b, c, d. И я проектирую производный класс B и я...

Базовый класс Complex и производный класс для реализации квадратных матриц
1) Создайте базовый класс Complex (комплексное число) для реализации комплексных чисел в...

Создать базовый класс Car (машина) и производный класс Lorry (грузовик): ООП ошибки
Создать базовый класс Car (машина), характеризуемый торговой маркой (строка), числом цилиндров,...

Создать базовый класс - Array и производный класс - Money для работы денежной суммы
ПОМОГИТЕ, ПОЖАЛУЙСТА, С ЗАДАЧЕЙ Создать базовый класс - Array и производный класс - Money для...

13
Эксперт С++
2919 / 1268 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
17.07.2013, 15:50 2
Строго говоря, второй вывод может напечатать все, что угодно. В том числе - ноль. (Ноль тоже относится к понятию "мусор".) Видимо, так звезды встали, что в той ячейке памяти оказался ноль.

"с хабаром вернулся - чудо, живой вернулся - удача, патрульная пуля мимо - везенье, а все остальное - судьба..." (с)
1
Эксперт С++
1889 / 1237 / 354
Регистрация: 16.05.2013
Сообщений: 3,239
Записей в блоге: 6
17.07.2013, 15:59 3
BigLow, тебя эта строчка не смущает?
C++
1
    ptrCircle=(CCircle *)ptrPoint;
Сделай так:
C++
1
    ptrCircle=&circle;
0
55 / 55 / 6
Регистрация: 07.07.2013
Сообщений: 345
17.07.2013, 16:04  [ТС] 4
Цитата Сообщение от Ilot Посмотреть сообщение
Сделай так:
C++
1
ptrCircle=&circle;
там смысл в том, что круг рассматривается как точка

конечно получается непонятно что, но это чтобы лучше понять наследование
0
Эксперт С++
2919 / 1268 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
17.07.2013, 16:09 5
Наоборот: точка (ptrPoint) рассматривается как круг (ptrCircle).

Не по теме:

Я бы высказался в том смысле, что Дейтел тут свалял дурака. Отношение наследования реализует отношение "является": объект класса-потомка является одновременно и объектом класса-предка, и поэтому может быть подставлен во всех случаях, когда по логике программы требуется объект класса-предка (LSP). Круг же не является точкой.

0
55 / 55 / 6
Регистрация: 07.07.2013
Сообщений: 345
17.07.2013, 16:11  [ТС] 6
Цитата Сообщение от CheshireCat Посмотреть сообщение
Ноль тоже относится к понятию "мусор".
теперь буду знать. обычно когда переменная содержит мусор, то при выводе показывает огромное положительное или отрицательное число

Добавлено через 1 минуту
Цитата Сообщение от CheshireCat Посмотреть сообщение
Наоборот: точка (ptrPoint) рассматривается как круг (ptrCircle)
да у меня от этого уже голова кругом
0
Эксперт С++
2919 / 1268 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
17.07.2013, 16:13 7
Не совсем так. "Мусор" может показать что угодно - "огромное" положительное или отрицательное число, или "не очень огромное", или "совсем малюсенькое", или ноль... вообще - что угодно. В прямом смысле слова. Ноль тоже подходит под критерий "что угодно". :-)
1
Эксперт С++
1889 / 1237 / 354
Регистрация: 16.05.2013
Сообщений: 3,239
Записей в блоге: 6
17.07.2013, 16:16 8
там смысл в том, что круг рассматривается как точка
А понятно. Что то я сразу не сообразил.
Ответ на вопрос может стоит поискать в самом компиляторе. Возможно он при приведении типов автоматически обнуляет свободные поля?

Проверил: добовил еще одно поле в класс Circle/Та же басня - значение нуль. Значит действительно компилятор при приведении типов обнуляет свободные поля.
1
Эксперт С++
2919 / 1268 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
17.07.2013, 16:21 9
Нет, он ничего не "обнуляет". Просто - совпадение.....
Кстати, компиль какой? и как транслируешь - в debugили в release ?
0
55 / 55 / 6
Регистрация: 07.07.2013
Сообщений: 345
17.07.2013, 16:23  [ТС] 10
я в debug транслирую
visual studio 2010
0
2572 / 2188 / 233
Регистрация: 03.07.2012
Сообщений: 7,901
Записей в блоге: 1
17.07.2013, 16:35 11
Да ничего он не обнуляет. Нельзя приводить тип родителя к типу наследника - в полях наследника будет мусор.
1
Мимино
17.07.2013, 16:46
  #12

Не по теме:

Цитата Сообщение от CheshireCat Посмотреть сообщение
Не по теме:
Я бы высказался в том смысле, что Дейтел тут свалял дурака. Отношение наследования реализует отношение "является": объект класса-потомка является одновременно и объектом класса-предка, и поэтому может быть подставлен во всех случаях, когда по логике программы требуется объект класса-предка (LSP). Круг же не является точкой.
Пример не очень удачный, т.к. сложный для понимания, но тем не менее правильный. Круг на плоскости можно представить как точку центра окружности и радиуса (как в примере). Этого достаточно, чтобы вычислить любую точку на окружности. Получается, что по его примеру круг является точкой(началом координат отрезка "радиус") + длина радиуса.
А вот следующие примеры с наследником класса Circle - класс Cylindr, который определяется еще и высотой, действительно лажа выходит, т.к. у точки нет z-координаты. Это справедливо только если центры оснований цилиндра лежат в плоскости (x, y)

0
CheshireCat
17.07.2013, 16:59
  #13

Не по теме:

Цитата Сообщение от Мимино Посмотреть сообщение
Круг на плоскости можно представить как точку центра окружности и радиуса (как в примере). Этого достаточно, чтобы вычислить любую точку на окружности. Получается, что по его примеру круг является точкой(началом координат отрезка "радиус") + длина радиуса.
Ннуууу..... мне, конечно, кажется, что это объяснение "притянуто за уши" (то, что называется "подгонка результата под ответ"), но - ладно, допускаю возможность и такого толкования... Хотя кмк здесь мы имеем в чистом виде отношение агрегирования "включает": круг включает (содержит в себе) точку центра и радиус.

Короче, к этим надуманным примерам в книжках от Дейтела/Шилдта/etc. надо относиться изрядно критически.

0
512 / 464 / 81
Регистрация: 07.04.2012
Сообщений: 869
Записей в блоге: 1
17.07.2013, 17:19 14
Цитата Сообщение от BigLow Посмотреть сообщение
если указателю на производный класс присвоить указатель на базовый
Так не стоит делать. Наоборот, без проблем указателю на базовый класс можно присвоить адрес объекта производного класса. То есть, если круг наследуется от точки:

C++
1
2
3
4
5
6
7
CPoint      point(1.1, 2.2);
CCircle     circle(5.5, 6.6, 10.0);
 
CPoint * ptrPoint;
    
ptrPoint = &point; // в указателе - адрес объекта "точка"
ptrPoint = &circle; // теперь в этом указателе - адрес объекта "круг"
Другое дело, как корректно вызывать методы по данному указателю. Тут могут понадобиться виртуальные функции.
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.07.2013, 17:19

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Указатели в базовом классе на базовый класс и производный класс
Пишу контейнер &quot;Бинарное дерево поиска&quot; для частотного словаря. С самим контейнером особо...

Создать базовый класс Triad и производный класс vector3D
Помогите пожалуйста с заданием. Часть кода(vector3D) сделал, вроде работает Нужно помочь с классом...

Создать базовый класс Polygon и производный класс Triangle
Создать базовый класс Polygon (многоугольник). Класс должен содержать методы для рисования...

Наследование: базовый класс Квадрат, производный класс Пирамида
Помогите, пожалуйста!:cry: Добавлено через 6 минут Создать класс КВАДРАТ, член класса- длинна...


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

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

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