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

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

Войти
Регистрация
Восстановить пароль
 
 
Divergence
7 / 7 / 0
Регистрация: 19.06.2013
Сообщений: 174
#1

Чем может быть чревато создание в классе адреса на другой класс - C++

09.06.2014, 02:15. Просмотров 608. Ответов 20
Метки нет (Все метки)

Всем привет!
Я решил не заморачиваться с наследованием, так как у меня каждый класс использует только свои узкоспециализированные функции. А вот некоторые данные из класса все равно таскать приходится.
Таким образом, у меня возникла вот такая, можно сказать, иерархия:

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
class Object //Хранит в себе всю информацию о любом объекте
{
public:
float o1;
float o2;
float o3;
Object() //Конструктор
{
o1 = 1;
o2 = 2;
o3 = 3;
}
~Object(){} //Деструктор
void ObjectFunc1(){} //Функция 1
void ObjectFunc2(){} //Функция 2
};
 
class Paint //Клас Paint не наследует класс Object, тем не менее имеет внутри себя один экземпляр класса Object
{
public:
Object* MyObject; //Адрес экземпляра класса Object
Paint(Object* fObject) //Конструктор
{
MyObject = fObject; //Копирование в переменную класса Paint адреса уже существующего экземпляра Object
}
~Paint(){} //Деструктор
void PaintFunc1(){} //Функции-члены Paint
void PaintFunc2(){} 
};
 
void WinMain()
{
Object *MyObject = new Object;
Paint   *MyPaint   = new Paint(MyObject);
 
//Используем Paint как хотим
 
delete Object;
delete Paint1;
}
Вот так у меня это реализовано.
Вопрос в том, есть ли в такой реализации подводные камни, если есть, то какие??
Буду благодарен за любые предупреждения и мысли по этому поводу.
Лично мне кажется, что никакой опасности нет, тем не менее чутье ноет о том, что здесь не совсем все так просто как кажется...
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.06.2014, 02:15
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Чем может быть чревато создание в классе адреса на другой класс (C++):

Сколько может быть конструкторов в классе? - C++
Только один или можно больше?

В чем может быть ошибка? - C++
Вот программа: #include "stdafx.h" #include <iostream> #include <stdio.h> #include <math.h> #include <stdlib.h> #include...

В чем может быть ошибка, и как её вылечить? - C++
Проблема такая. Покуда я студент, то пичкают нас всяческой дрянью, и вот настал язык Си. С С++ я знаком, и ноутбук с никсами прекрасно...

В чем может быть ошибка? (пример с побитовым сдвигом) - C++
Всем доброго дня) В одной из книжек по С++ (Horton) наткнулся на такую вот небольшую задачку: unsigned s = 555; int i = (s >>...

В чем может быть ошибка? (передача аргументов функции) - C++
Есть двумерный массив, симулирующий игровое поле (0 означают пустоту, 8 игрок) Есть некая функция, которую я хочу использовать просто для...

Программа не работает, но ошибок не выдает. В чем может быть ошибка? - C++
#include <iostream> #include <math.h> #include <cstdlib> #define m 8 using namespace std; int main() { int...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Nekto
342 / 287 / 10
Регистрация: 23.03.2012
Сообщений: 838
09.06.2014, 02:17 #2
Голые указатели всегда опасны.
Divergence
7 / 7 / 0
Регистрация: 19.06.2013
Сообщений: 174
09.06.2014, 02:25  [ТС] #3
У меня структура даже сложнее чем я указал:
есть еще класс stage, который имеет в себе Paint и похожие по структуре на Paint классы и манипулирует ими тем же способом. Я планировал сделать ЕЩЕ класс, который будет манипулировать stage'ами, но у меня полезли какие-то настолько странные ошибки, что я отказался от идеи так глубоко залезать по классам и сделал просто функцию.
Тем не менее такая сложная иерархия классов осталась (получается, что один класс имеет доступ к экземплярам двух классов, которые еще и создан один из другого).
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6447 / 3094 / 306
Регистрация: 04.12.2011
Сообщений: 8,567
Записей в блоге: 4
09.06.2014, 03:00 #4
Divergence, использование объектов классов или указателей на объекты классов в качестве полей классов это нормально. Если говорить об указателях, то это чуть более трудоёмко чем просто использовать сам объект. Разница почти та же, что и при использовании переменной указателя на стеке, но тяжелее то, что конструкторов не один и везде нужно побеспокоиться о инициализации указателя. То есть нужно выделить память, чем-то заполнить, а в деструкторе удалить.
В Вашем конструкторе копируется указатель и Вы не можете знать указывает он на что-то разумное или нет. Обычно в таких случаях делают иначе. Но сначала нужно написать конструктор без параметров и или закрыть его (тогда он может быть пустой) или выделить в нём память под объект и заселить её объектом по умолчанию. Закрывать - прём узкий. Это значит, что контейнеры STL использовать не выйдет, например.
Написав открытые конструкторы Вы будете уверены, что как бы не создавался экземпляр, он будет инициализирован. А в конструкторе копирования тоже нужно бы выделить память и скопировать в неё объект из оригинала почленно. В деструкторе удалить. Тут лучше ничего не делать руками.
Divergence
7 / 7 / 0
Регистрация: 19.06.2013
Сообщений: 174
09.06.2014, 03:16  [ТС] #5
Цитата Сообщение от IGPIGP Посмотреть сообщение
Divergence, использование объектов классов или указателей на объекты классов в качестве полей классов это нормально. Если говорить об указателях, то это чуть более трудоёмко чем просто использовать сам объект. Разница почти та же, что и при использовании переменной указателя на стеке, но тяжелее то, что конструкторов не один и везде нужно побеспокоиться о инициализации указателя. То есть нужно выделить память, чем-то заполнить, а в деструкторе удалить.
В Вашем конструкторе копируется указатель и Вы не можете знать указывает он на что-то разумное или нет. Обычно в таких случаях делают иначе. Но сначала нужно написать конструктор без параметров и или закрыть его (тогда он может быть пустой) или выделить в нём память под объект и заселить её объектом по умолчанию. Закрывать - прём узкий. Это значит, что контейнеры STL использовать не выйдет, например.
Написав открытые конструкторы Вы будете уверены, что как бы не создавался экземпляр, он будет инициализирован. А в конструкторе копирования тоже нужно бы выделить память и скопировать в неё объект из оригинала почленно. В деструкторе удалить. Тут лучше ничего не делать руками.
IGPIGP, спасибо за ответ!
Если честно, я не очень понимаю эти опасения по поводу того, что указатель может не указывать на существующую область памяти... у меня в коде сначала выделяется память, только затем в новый класс передается указатель. В случае такого грамотного подхода (когда ничего не забыто) опасности никакой нет?
Или все же могут быть косяки?
Например, я смутно предполагаю ситуацию, что в какой-то момент вызовется деструктор, который освободит память, на которую у меня несколько указателей по определению... Соответственно, несколько указателей будут указывать на пустоту. Однако, логика программы такова, что жизнь одного класса без другого просто не имеет смысла, поэтому уничтожаться они будут строго один за другим до самого конца. Остаются ли какие-то опасности при такой ситуации?
Nekto
342 / 287 / 10
Регистрация: 23.03.2012
Сообщений: 838
09.06.2014, 03:20 #6
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Divergence Посмотреть сообщение
IGPIGP, спасибо за ответ!
Если честно, я не очень понимаю эти опасения по поводу того, что указатель может не указывать на существующую область памяти... у меня в коде сначала выделяется память, только затем в новый класс передается указатель. В случае такого грамотного подхода (когда ничего не забыто) опасности никакой нет?
Или все же могут быть косяки?
Например, я смутно предполагаю ситуацию, что в какой-то момент вызовется деструктор, который освободит память, на которую у меня несколько указателей по определению... Соответственно, несколько указателей будут указывать на пустоту. Однако, логика программы такова, что жизнь одного класса без другого просто не имеет смысла, поэтому уничтожаться они будут строго один за другим до самого конца. Остаются ли какие-то опасности при такой ситуации?
Зачем тогда создавать объект снаружи и передавать указатель на него? Почему бы не создать его внутри?
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6447 / 3094 / 306
Регистрация: 04.12.2011
Сообщений: 8,567
Записей в блоге: 4
09.06.2014, 03:22 #7
Цитата Сообщение от Divergence Посмотреть сообщение
В случае такого грамотного подхода (когда ничего не забыто) опасности никакой нет?
В случае такого грамотного подхода, само понятие опасности теряет смысл.
Какая может быть опасность для человека, которого не испугать? А что мешает написать конструктор по умолчанию, конструктор копии, деструктор и перегрузить оператор присваивания?
Divergence
7 / 7 / 0
Регистрация: 19.06.2013
Сообщений: 174
09.06.2014, 03:30  [ТС] #8
Цитата Сообщение от Nekto Посмотреть сообщение
Зачем тогда создавать объект снаружи и передавать указатель на него? Почему бы не создать его внутри?
Спасибо за идею! Действительно, я подумаю об этом. Небольшие трудности создает только то, что в дальнейшем, мне может потребоваться один класс отдельно от другого для каких-то еще не придуманных сейчас целей. Это удерживает. Но скорее всего я последую совету

Добавлено через 5 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
А что мешает написать конструктор по умолчанию, конструктор копии, деструктор и перегрузить оператор присваивания?
Просто не могу заставить себя делать что-то сложное, когда можно сделать просто. Я сделал просто и понятно для себя, без лишних наворотов. Если бы я точно понимал какие плюсы мне даст вся эта перегрузка и куча конструкторов, и я бы эти плюсы посчитал существенными, то конечно сделал бы так.
Именно потому, я и написал вопрос на форуме: я сделал просто, хотя обычно люди делают сложно, и причин для такой сложности я не увидел. Вот и хочу послушать аргументы в пользу сложного подхода.
Но пока, на такую сложную модель переходить я не переубедился
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6447 / 3094 / 306
Регистрация: 04.12.2011
Сообщений: 8,567
Записей в блоге: 4
09.06.2014, 03:35 #9
Цитата Сообщение от Nekto Посмотреть сообщение
Зачем тогда создавать объект снаружи и передавать указатель на него? Почему бы не создать его внутри?
Конечно!
Цитата Сообщение от IGPIGP Посмотреть сообщение
сначала нужно написать конструктор без параметров и ... выделить в нём память под объект и заселить её объектом по умолчанию.
Ведь при попытке объявить такой объект как сейчас на стеке нужно будет каждый раз инициализировать его руками. А заполнить вектор такими объектами? Лучше пусть это делает конструктор, а прямой доступ к указателю снаружи и закрыть можно бы.
Jupiter
Каратель
Эксперт С++
6553 / 3973 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
09.06.2014, 12:21 #10
Цитата Сообщение от Divergence Посмотреть сообщение
Вопрос в том, есть ли в такой реализации подводные камни, если есть, то какие??
C++
1
Paint paint(0);
Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
09.06.2014, 14:07 #11
Divergence, удалять объекты надо в порядке обратном их созданию. Т.е. сначала MyPaint, потом MyObject. А вообще, см. что такое "умные" указатели.
Цитата Сообщение от Jupiter Посмотреть сообщение
C++
1
Paint paint(0);
По приведенному ТС коду, проблемы с нулевым указателем нет.
Jupiter
09.06.2014, 14:33
  #12

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
По приведенному ТС коду, проблемы с нулевым указателем нет.
додо, конечно же у ТС все методы пустые и просто так хранится указатель

Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
09.06.2014, 15:27 #13
Jupiter, додомывать можно сколько угодно. Может у него там и if'ами всё обвешано с проверкой на нуль. Но чего не показано, того не показано.
Jupiter
09.06.2014, 15:34
  #14

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
сколько угодно
Цитата Сообщение от Tulosba Посмотреть сообщение
нельзя идти на поводу у ТС. Надо жесткой хваткой взять его и сказать: "что же ты делаешь! Так нельзя.Потому что: раз, два и три".
занавес...

Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
09.06.2014, 15:38 #15
Jupiter, не вижу связи. Одно дело, видеть кривой код и критиковать его. И совсем другое - критиковать по результатам своих фантазий.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.06.2014, 15:38
Привет! Вот еще темы с ответами:

В чем может быть ошибка. Расстояние между вершинами дерева - C++
Входные данные: Первая строка содержит количество вершин в дереве n(1<=n<=500000). Вершины имеют значения от 0 до n-1. В следующих n-1...

Программа не работает на русском языке. В чем может быть ошибка? - C++
#include<iostream> #include <string> using namespace std; int main() { setlocale (LC_ALL, "rus"); for (int countinue = 0;...

Реализовать класс Account, представляющий собой банковский счет. В классе должны быть четыре поля - C++
Реализовать класс Account, представляющий собой банковский счет. В классе должны быть четыре поля: фамилия владельца, номер счета, процент...

задание из книги стивен прата 6 издание глючит. в чем может быть ошибка - C++
собрал задачу, ставлю текстовый файл внутри программы, с цифровыми данными, а он не работает. файл сам рабочий, так как другая программа...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
09.06.2014, 15:38
Ответ Создать тему
Опции темы

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