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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
LuxArt
34 / 21 / 2
Регистрация: 14.11.2013
Сообщений: 85
#1

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

17.11.2013, 11:41. Просмотров 634. Ответов 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.11.2013, 11:41
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Не могу организовать иерархию классов (C++):

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

Спроектировать иерархию классов - C++
Вот моё задание. Наследование классов Спроектировать иерархию классов На основе имеющегося базового класса (“суперкласс”) создать...

Разработать иерархию классов - C++
Разработать иерархию классов родительский абстрактный класс Vehicle с двумя чистыми виртуальными функциями и дочерним классом Car . Для...

Определить иерархию классов - C++
рабочий, кадры, инженер, администрация Для определения иерархии классов связать отношением наследования классы: рабочий, кадры, инженер,...

Не получается создать иерархию классов - C++
Пытаюсь реализовать что-то вроде шаблонного метода: основная логика отрисовки лежит в базовом классе Shape (какие цвета берем, что...

Создать иерархию классов датчик - C++
Создать иерархию классов датчик – абстрактный базовый класс и датчики температуры, влажности и скорости ветра. Для каждого класса...

15
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
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
LuxArt
34 / 21 / 2
Регистрация: 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
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
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
LuxArt
34 / 21 / 2
Регистрация: 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
StackOverflow
All rights reserved.
91 / 81 / 5
Регистрация: 03.08.2013
Сообщений: 258
17.11.2013, 17:44 #6
А можно такой вопрос задать, зачем вам возится с базовым классом? Наплодили его потомков вот и пользуйтесь их услугами напрямую через их объекты)
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
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
LuxArt
34 / 21 / 2
Регистрация: 14.11.2013
Сообщений: 85
17.11.2013, 17:55  [ТС] #8
StackOverflow, Хочу создать массив объектов базового класса. Точнее указателей на базовый класс.
И потом динамически выделить для них память, т.е. создать производные объекты (точка, круг, ...)
Потом обращаться к нужным функциям только через указатель на базовый класс

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

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

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

Не по теме:

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

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

Добавлено через 1 минуту
Цитата Сообщение от stima Посмотреть сообщение
LuxArt Дайте определение массив и поймете, что Ваша идея не совсем коректна.
Корректна. Каждый элемент в массиве - это указатель. А на что он указывает это уже другой вопрос)
0
Avazart
Нарушитель
Эксперт С++
7232 / 5404 / 293
Регистрация: 10.12.2010
Сообщений: 23,952
Записей в блоге: 17
17.11.2013, 18:18 #12
Цитата Сообщение от LuxArt Посмотреть сообщение
У меня такая одна интересная идея есть.
Почитай по фабрики

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

Так что если у Вас массив элементов баззового класса, а Вы в процессе прохода по массиву, хотите от них вызовов дочерних методов и эти методы не вписываются в баззовый класс (через virtual), то стоит подумать, чтобы добавить еще один(или несколько) массивов, которые будут хранить ОДНОТИПНЫЕ элементы.
1
агерон
268 / 267 / 33
Регистрация: 12.10.2009
Сообщений: 1,061
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
LuxArt
34 / 21 / 2
Регистрация: 14.11.2013
Сообщений: 85
17.11.2013, 21:30  [ТС] #15
Цитата Сообщение от агерон Посмотреть сообщение
Avazart, про фабрики ему читать пока рано пусть сперва выучит основы ООП
Почему это рано? Очень даже интересно почитать.
А основы ООП я итак знаю.
Даже если я и ошибся и чего-то недопонимаю, то ничего страшного
0
17.11.2013, 21:30
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.11.2013, 21:30
Привет! Вот еще темы с ответами:

Создать иерархию классов язык с++ - C++
Создать иерархию классов язык с++ Жидкость&lt;-Напиток Жидкость&lt;-Топливо Жидкость&lt;-Реагент Жидкость - абстрактный класс?...

Как лучше сделать иерархию классов? - C++
Здравствуйте! Мой вопрос заключается в том, что я хочу понять как лучше сделать иерархию классов: шаблонами или простым множественных...

Создать иерархию классов химических реакторов - C++
Помогите разобраться в задании: Создал базовый класс, определил в нем конструктор копирования, перегрузил оператор присваивания...

Реализовать иерархию классов Компьютер-Ноутбук - C++
Помогите, пожалуйста. Условие задачи: частота процессора (в МГц), количество ядер, объем памяти (в МБ), объем жесткого...


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

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

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