Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
36 / 23 / 10
Регистрация: 14.11.2013
Сообщений: 85
1

Не могу организовать иерархию классов

17.11.2013, 11:41. Показов 1136. Ответов 15
Метки нет (Все метки)

Всем привет!
Нужен совет как правильно сделать наследование.
Чтобы через указатель базового класса (Форма) можно было бы создать объект производного класса (Точка).
А так же чтобы можно было вызывать методы из производного.

Shapes.h
Кликните здесь для просмотра всего текста
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
Shapes.h:
 
#ifndef SHAPES_H
#define SHAPES_H
#include <iostream>
 
 
class Shape
{
public:
    virtual ~Shape() {};
 
    virtual void PrintShapeName() const = 0;
    virtual void Print() const = 0;
    virtual double GetArea() const      { return 0.0; };
    virtual double GetVolume() const    { return 0.0; };
};
 
 
class Point : public Shape
{
private:
    double      m_x;
    double      m_y;
 
public:
    Point(double x=0.0,  double y=0.0);
    ~Point();
 
    void SetX(double x);
    void SetY(double y);
    void SetPoint(double x,  double y);
 
    double GetX() const;
    double GetY() const;
 
    virtual void PrintShapeName() const override;
    virtual void Print() const override;
};
 
 
class Circle : public Point
{
private:
    double      m_radius;
 
public:
    Circle(double x=0.0,  double y=0.0,  double radius=1.0);
    ~Circle();
 
    void SetRadius(double radius);
    double GetRadius() const;
};
 
#endif // SHAPES_H





main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <stdlib.h>
#include "include/Shapes.h"
 
 
int main()
{
    Shape   *shape;
 
    shape = new Point;
    shape->SetPoint(1.0, 1.0);  // Невозможно указать координаты точки! Этого метода нет в класса Shape
 
    system("pause");
    return 0;
}
Можно SetPoint() перенести в базовый, но мне не нравится эта идея. Каждый раз при добавлении нового класса придется вносить изменения в базовый

Дайте совет что делать
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.11.2013, 11:41
Ответы с готовыми решениями:

Разработать иерархию классов, демонстрирующее работу с коллекцией объектов разных классов
Задание: Разработать в соответствии с индивидуальным заданием иерархию классов и приложение,...

Организовать иерархию классов
В общем, ситуация такая: пишется что-то наподобие простенького движка для шариков, которые будут...

Организовать иерархию классов
Организовать иерархию классов, в которых предусмотреть закрытые поля с соответствующими свойствами,...

Организовать иерархию классов: дом, улица, город
Обязательно реализовать в каждом классе метод ToString, который будет форматировать вывод...

15
:)
Эксперт С++
4766 / 3260 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
17.11.2013, 12:21 2
Цитата Сообщение от LuxArt Посмотреть сообщение
Дайте совет что делать
Если просто надо по указателю на базовый класс вызывать методы дочернего, то надо приводить типы:
C++
1
2
3
4
5
Point* p = dynamic_cast<Point*>(shape);
if( p ) // shape является Point
{
   p->SetPoint();
}
1
36 / 23 / 10
Регистрация: 14.11.2013
Сообщений: 85
17.11.2013, 17:01  [ТС] 3
Цитата Сообщение от Tulosba Посмотреть сообщение
надо приводить типы:
Можно ли это сделать без приведения типов? Чтобы через указатель базового класса вызвать функцию из производного?
Понятно, что базовые классы ничего не знают о производных, но все таки

Как-нибудь так
C++
1
2
3
    Shape   *shape = new Point;
 
    (Point *)shape->SetPoint(1.1, 2.2);
0
:)
Эксперт С++
4766 / 3260 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
17.11.2013, 17:06 4
Цитата Сообщение от LuxArt Посмотреть сообщение
C++
1
(Point *)shape->SetPoint(1.1, 2.2);
Видимо имелось в виду:
C++
1
((Point *)shape)->SetPoint(1.1, 2.2);
Но это ведь тоже приведение типа, только в Си-стиле.
1
36 / 23 / 10
Регистрация: 14.11.2013
Сообщений: 85
17.11.2013, 17:39  [ТС] 5
Цитата Сообщение от Tulosba Посмотреть сообщение
((Point *)shape)->SetPoint(1.1, 2.2);
Спасибо все работает

C++
1
2
3
4
5
    Shape   *shape = new Point;
 
    ((Point *)shape)->SetPoint(1.1, 2.2);
 
    ((Point *)shape)->Print();
Добавлено через 2 минуты
Оказывается ничего сложного нет. Только скобки были неправильно расставлены. Из-за этого и не компилировалась программа

Добавлено через 16 минут
Еще один вопрос есть.
Смотрите. Каждый раз при выборе любой функции из производного класса, этот указатель приходится приводить к правильному типу, нужно всякий раз указывать (Circle *):

C++
1
2
3
4
5
6
7
    Shape   *shape = new Circle;
 
    ((Circle *)shape)->SetPoint(1.1, 2.2);
    ((Circle *)shape)->SetRadius(10.0);
 
    std::cout << "x = " << ((Circle *)shape)->GetX() << ", y = " << ((Circle *)shape)->GetY() << std::endl;
    std::cout << "Площадь = " << ((Circle *)shape)->GetArea() << std::endl;
Можно от этого избавиться?
0
All rights reserved.
92 / 82 / 24
Регистрация: 03.08.2013
Сообщений: 258
17.11.2013, 17:44 6
А можно такой вопрос задать, зачем вам возится с базовым классом? Наплодили его потомков вот и пользуйтесь их услугами напрямую через их объекты)
0
:)
Эксперт С++
4766 / 3260 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
17.11.2013, 17:47 7
Цитата Сообщение от LuxArt Посмотреть сообщение
Можно от этого избавиться?
Вводим дополнительную переменную:
C++
1
2
3
Circle* circle = (Circle *)shape;
circle->SetPoint(1.1, 2.2);
cirlce->SetRadius(10.0);
но лучше использовать dynamic_cast
0
36 / 23 / 10
Регистрация: 14.11.2013
Сообщений: 85
17.11.2013, 17:55  [ТС] 8
StackOverflow, Хочу создать массив объектов базового класса. Точнее указателей на базовый класс.
И потом динамически выделить для них память, т.е. создать производные объекты (точка, круг, ...)
Потом обращаться к нужным функциям только через указатель на базовый класс

А сейчас тренируюсь с этими классами. Пробую как лучше все организовать

Добавлено через 6 минут
Цитата Сообщение от Tulosba Посмотреть сообщение
Вводим дополнительную переменную:
Хотелось бы без дополнительной переменной)

ладно, пожалуй пока хватит. Думаю по другому никак не получится. Нужно всегда приводить указатель
0
Avazart
17.11.2013, 18:00
  #9

Не по теме:

Может стоит задаться вопросом стоит ли тут использовать наследование ?

0
499 / 349 / 93
Регистрация: 22.03.2011
Сообщений: 1,111
17.11.2013, 18:04 10
LuxArt Дайте определение массив и поймете, что Ваша идея не совсем коректна.
0
36 / 23 / 10
Регистрация: 14.11.2013
Сообщений: 85
17.11.2013, 18:12  [ТС] 11
Цитата Сообщение от Avazart Посмотреть сообщение
Может стоит задаться вопросом стоит ли тут использовать наследование ?
У меня такая одна интересная идея есть. Есть указатель на базовый класс (Форма). Через этот указатель я могу создать круг, квадрат, цилиндр. Да и вообще все что пожелаю. И для этого нужен только один указатель! Другие переменные даже не нужны. Таким способом я могу создать один объект.
А если нужно несколько объектов, то для этого подойдет массив указателей на базовый класс

Добавлено через 1 минуту
Цитата Сообщение от stima Посмотреть сообщение
LuxArt Дайте определение массив и поймете, что Ваша идея не совсем коректна.
Корректна. Каждый элемент в массиве - это указатель. А на что он указывает это уже другой вопрос)
0
Эксперт С++
8359 / 6097 / 610
Регистрация: 10.12.2010
Сообщений: 28,426
Записей в блоге: 30
17.11.2013, 18:18 12
Цитата Сообщение от LuxArt Посмотреть сообщение
У меня такая одна интересная идея есть.
Почитай по фабрики

http://ru.wikipedia.org/wiki/%... 8%D1%8F%29
1
499 / 349 / 93
Регистрация: 22.03.2011
Сообщений: 1,111
17.11.2013, 18:28 13
Цитата Сообщение от LuxArt Посмотреть сообщение
Корректна. Каждый элемент в массиве - это указатель. А на что он указывает это уже другой вопрос)
В конрне не верно. Массив это набор ОДИНОТИПНЫХ элементов. А то что он реализуется через указатели это уже совсем другое.

Так что если у Вас массив элементов баззового класса, а Вы в процессе прохода по массиву, хотите от них вызовов дочерних методов и эти методы не вписываются в баззовый класс (через virtual), то стоит подумать, чтобы добавить еще один(или несколько) массивов, которые будут хранить ОДНОТИПНЫЕ элементы.
1
441 / 297 / 62
Регистрация: 12.10.2009
Сообщений: 1,159
17.11.2013, 19:04 14
Вы не понимаете основ ООП, что такое базовый класс, через указатель базового класса вы НИКОГДА не вызовете тех функций классов потомков которые не определены как виртуальные в классе предке т. е.
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
class CBase
{
    public:
        virtual int GetBaseProperty();
        virtual void SetBaseProperty(int value);
}
 
class CExtended:public CBase
{
    public:
        virtual int GetBaseProperty() overidde;
        virtual void SetBaseProperty(int value) overidde;
        virtual int GetExtendedProperty() overidde;
        virtual void SetExtendedProperty(int value) overidde;               
} 
 
void main()
{
    CExtended *extended = new CExtended();
    CBase *base = extended;
    extended -> SetBaseProperty(5); //так можно     
    extended -> SetExtendedProperty(5); //и так можно 
    base->SetBaseProperty(5);// и так можно, т к класс СBase "знает" про SetBaseProperty, мы вызовем extended -> SetBaseProperty основываясь на VMT
    base->SetExtendedProperty(5) // а вот так нельзя т. к. класс CBase ничего "не знает" про SetExtendedProperty и это вызовет ошибку компиляции  
}
Добавлено через 1 минуту
Avazart, про фабрики ему читать пока рано пусть сперва выучит основы ООП
0
36 / 23 / 10
Регистрация: 14.11.2013
Сообщений: 85
17.11.2013, 21:30  [ТС] 15
Цитата Сообщение от агерон Посмотреть сообщение
Avazart, про фабрики ему читать пока рано пусть сперва выучит основы ООП
Почему это рано? Очень даже интересно почитать.
А основы ООП я итак знаю.
Даже если я и ошибся и чего-то недопонимаю, то ничего страшного
0
441 / 297 / 62
Регистрация: 12.10.2009
Сообщений: 1,159
17.11.2013, 22:48 16
Проблема в том что Фабрика это шаблон проектирования которые желательно читать после осознания ООП, я вам не запрещаю читать про паттерны, упаси боже, просто не факт что все прочитанное вы сможете корректно принять, в связи с непониманием что такое паттерны и когда их уместно применять

Добавлено через 1 минуту
Данные выводы об вашем уровне осознания ООП следуют из вашего непонимания как нужно работать с классами
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.11.2013, 22:48

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

Как можно организовать иерархию классов для работы с графами
Подскажите варианты того, как можно организовать иерархию классов для работы с графами (или создать...

Не могу понять иерархию классов java
Я не могу понять что есть что. Вот к примеру, есть пакет java.util.collection и следующая схема ...

Создать иерархию классов
создать иерархию класса Animal &gt;Cat &gt;Siamskaya Persidskai и определить , общие методы и уникальные...

Построить иерархию классов
Задание: 1)Создать абстрактный класс Trans с методами позволяющим вывести на экран информацию о...


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

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

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