Как хранить объекты ?
От: Сергей  
Дата: 11.10.02 09:40
Оценка:
Люди, подскажите:
создаю объект своего класса MyClass, который в качестве переменных-членов имеет объекты других моих классов, а также указатели на объекты моих классов, которые(указатели) используются для динамического выделения памяти под массивы этих объектов.
Назрела необходимость создавать произвольное число объектов класса MyClass и соответственно их нужно где-то хранить.
пробовал их хранить в массиве CArray, но он не принимает в качестве аргументов объекты MyClass уже проинициализированные
    CArray<MyClass, MyClass> m_Array;
        ...................
    MyClass myclass;
    myclass.Init(10,10); <- выделяет память под массивы объектов переменных членов объекта класса MyClass
    m_Sheet.Add(sheet);  <- ругается "No copy constructor available for class 'MyClass'"

, т.е. принимает только вновь созданные
    MyClass myclass;
    m_Sheet.Add(sheet);  <- все ок

что это за "конструктор копирования" и как мне решить проблему хранения этих объектов при условии, что хранимый объект может менять свои размеры, т.е. динамически выделять блоки памяти и удалять их?
Re: Как хранить объекты ?
От: Vyacheslav Koltovich  
Дата: 11.10.02 10:02
Оценка: 16 (2)
Не совсем понятна ситуация, тем более что код видимо строками из рахных мест выдергивался. Могу ответить на последнюю часть вопроса.

Конструктор копирования это конструктор, который вызывается когда создаваемый объект инициализируется существующим объектом того же класса.
Например:
class CMyClass
{
...
       CMyClass(const CMyClass&)
...
}

CMyClass a;
CMyClass b(a);
CMyClass c = a;

Здесь во всех трех случаях вызывается конструктор копирования.
Он же используется при передаче объекта в функцию по значению.

Если конструктор явно не определен, создается конструктор копирования по умолчанию, который просто побитово отражает состояние одного объекта на другой. Для простых объектов этого бывает достаточно, но уже в случае когда объект содержит указатели могут возникать ошибки (рантайм, не компиляции).

Что же касается хранения объектов, изменяющих размеры, то размеры-то как раз и не меняются. Грубо говоря, твой объект внутри своего "тела" хранит только указатели, которые всегда имеют фиксированный размер. Те самые массивы объектов, на которые они указывают, хранятся в куче и никакого отношения к объекту не имеют.

Вот, помог чем мог. Если было бы приведено больше кода, возможно сказал бы что-то более конкретное.

Здравствуйте Сергей, Вы писали:

С>Люди, подскажите:

С>создаю объект своего класса MyClass, который в качестве переменных-членов имеет объекты других моих классов, а также указатели на объекты моих классов, которые(указатели) используются для динамического выделения памяти под массивы этих объектов.
С>Назрела необходимость создавать произвольное число объектов класса MyClass и соответственно их нужно где-то хранить.
С>пробовал их хранить в массиве CArray, но он не принимает в качестве аргументов объекты MyClass уже проинициализированные
С>
С>    CArray<MyClass, MyClass> m_Array;
С>        ...................
С>    MyClass myclass;
С>    myclass.Init(10,10); <- выделяет память под массивы объектов переменных членов объекта класса MyClass
С>    m_Sheet.Add(sheet);  <- ругается "No copy constructor available for class 'MyClass'"

С>
С>

С>, т.е. принимает только вновь созданные
С>
С>    MyClass myclass;
С>    m_Sheet.Add(sheet);  <- все ок
С>

С>что это за "конструктор копирования" и как мне решить проблему хранения этих объектов при условии, что хранимый объект может менять свои размеры, т.е. динамически выделять блоки памяти и удалять их?
Re: Как хранить объекты ?
От: Karamat Беларусь  
Дата: 11.10.02 10:05
Оценка: 4 (1)
Здравствуйте Сергей, Вы писали:

С>Люди, подскажите:

С>создаю объект своего класса MyClass, который в качестве переменных-членов имеет объекты других моих классов, а также указатели на объекты моих классов, которые(указатели) используются для динамического выделения памяти под массивы этих объектов.
С>Назрела необходимость создавать произвольное число объектов класса MyClass и соответственно их нужно где-то хранить.
С>пробовал их хранить в массиве CArray, но он не принимает в качестве аргументов объекты MyClass уже проинициализированные
    CArray<MyClass, MyClass> m_Array;
        ...................
    MyClass myclass;
    myclass.Init(10,10); <- выделяет память под массивы объектов переменных членов объекта класса MyClass
    m_Sheet.Add(sheet);  <- ругается "No copy constructor available for class 'MyClass'"


Попробуйте использовать массив указателей:

CPtrArray m_myClasses;


MyClass *pClass;
pClass = new MyClass;
pClass->Init(10, 10);
m_myClasses.Add(pClass);


Вытащить объекты можно так:

MyClass *pClass;

for(int i = 0; i < m_myClasses.GetSize(); i++)
{
  pClass = (MyClass*)m_myClasses[i];
  pClass->SomeFunction();
}


Не забудте их удалить после использования
Re[2]: Как хранить объекты ?
От: Vyacheslav Koltovich  
Дата: 11.10.02 10:18
Оценка:
На самом деле это не выход. Возможно эту локульную проблему удастся обойти, но вообще ситуация ненормальная и она точно вылезет где-то еще. Лучше разобраться с ошибко компиляции здесь, чем потом ловить ошибки выполнения.

Здравствуйте Karamat, Вы писали:


K>Здравствуйте Сергей, Вы писали:


С>>Люди, подскажите:

С>>создаю объект своего класса MyClass, который в качестве переменных-членов имеет объекты других моих классов, а также указатели на объекты моих классов, которые(указатели) используются для динамического выделения памяти под массивы этих объектов.
С>>Назрела необходимость создавать произвольное число объектов класса MyClass и соответственно их нужно где-то хранить.
С>>пробовал их хранить в массиве CArray, но он не принимает в качестве аргументов объекты MyClass уже проинициализированные
K>
K>    CArray<MyClass, MyClass> m_Array;
K>        ...................
K>    MyClass myclass;
K>    myclass.Init(10,10); <- выделяет память под массивы объектов переменных членов объекта класса MyClass
K>    m_Sheet.Add(sheet);  <- ругается "No copy constructor available for class 'MyClass'"

K>
K>


K>Попробуйте использовать массив указателей:


K>
K>CPtrArray m_myClasses;

K>
K>MyClass *pClass;
K>pClass = new MyClass;
pClass->>Init(10, 10);
K>m_myClasses.Add(pClass);
K>


K>Вытащить объекты можно так:


K>
K>MyClass *pClass;

K>for(int i = 0; i < m_myClasses.GetSize(); i++)
K>{
K>  pClass = (MyClass*)m_myClasses[i];
K>  pClass->SomeFunction();
K>}
K>


K>Не забудте их удалить после использования
Re[3]: От модератора
От: Хитрик Денис Россия RSDN
Дата: 11.10.02 10:22
Оценка:
Здравствуйте Vyacheslav Koltovich, Вы много писали.

Вячеслав, будьте добры удалять ненужный текст из ответа. Это требование правил форума.
Правила нашего с вами форума.
Как правильно задавать вопросы. © 2001 by Eric S. Raymond; перевод: © 2002 Валерий Кравчук.
Re[4]: От модератора
От: Vyacheslav Koltovich  
Дата: 11.10.02 10:24
Оценка:
Здравствуйте Хитрик Денис, Вы писали:

ХД>Вячеслав, будьте добры удалять ненужный текст из ответа. Это требование правил форума.


Ок!
Re[2]: Как хранить объекты ?
От: Сергей  
Дата: 11.10.02 11:52
Оценка:
Здравствуйте Vyacheslav Koltovich, Вы писали:

VK>Не совсем понятна ситуация, тем более что код видимо строками из рахных мест выдергивался. Могу ответить на последнюю часть вопроса.


уточняю ситуацию:
class ChildClass
{
    int *p_int;
public:
    ChildClass() { p_int = NULL; };
    ~ChildClass() { if(p_int != NULL) delete [] p_int; };
    void SetData(int number)
    {
        p_int = new int[number];
    };
}

class MyClass
{
    ChildClass m_child;
    int *p_int;
public:
    MyClass() { p_int = NULL; };
    ~MyClass{} { if(p_int != NULL) delete [] p_int; };
    void Init(int i, int j)
    {
        m_child.SetData(i);
        p_int = new int[j];
    };
}

class CMyApp : public CWinApp
{
    .......
    CArray<MyClass, MyClass> m_Array;
    void Init();
    ..............
}

void CMyApp::Init()
{
    MyClass myclass;
    myclass.Init(10,10);
    m_Array.Add(myclass); <- ошибка, если не вызывать myclass.Init() ошибки нет
}

это упрощенный вариант в плане количества переменных- и функций-членов у классов ChildClass и MyClass, но сути это не меняет
Re[3]: Ищи в другом месте
От: Vi2 Удмуртия http://www.adem.ru
Дата: 11.10.02 12:17
Оценка: 4 (1)
Здравствуйте Сергей, Вы писали:

...
С>class MyClass
С>{
...
С>public:
С>    MyClass() { p_int = NULL; }; //<-- лишняя точка с запятой (Vi2)
С>    ~MyClass{} { if(p_int != NULL) delete [] p_int; };  //<-- лишняя точка с запятой (Vi2)
//    ~MyClass() //<-- деструктор так определяется (Vi2)
С>    void Init(int i, int j)
С>    {
С>        m_child.SetData(i);
С>        p_int = new int[j];
С>    }; //<-- лишняя точка с запятой (Vi2)
С>} //<-- нет точки с запятой (Vi2)
...

С>это упрощенный вариант в плане количества переменных- и функций-членов у классов ChildClass и MyClass, но сути это не меняет

Наверное, слишком упрощённый вариант. У меня после переделки синтаксических ошибок — всё скомпилировалось
Компилятору без разницы — вызываешь ты какую-то функцию перед ошибочно компилируемой строкой или нет.
С>    myclass.Init(10,10);
С>    m_Array.Add(myclass); <- если здесь ошибка

С>//    myclass.Init(10,10);
С>    m_Array.Add(myclass); <- то здесь она также будет!
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Ищи в другом месте
От: Сергей  
Дата: 11.10.02 12:39
Оценка:
Здравствуйте Vi2, Вы писали:

Vi2>Здравствуйте Сергей, Вы писали:


Vi2>
Vi2>...
С>>class MyClass
С>>{
Vi2>...
С>>public:
С>>    MyClass() { p_int = NULL; }; //<-- лишняя точка с запятой (Vi2)
С>>    ~MyClass{} { if(p_int != NULL) delete [] p_int; };  //<-- лишняя точка с запятой (Vi2)
Vi2>//    ~MyClass() //<-- деструктор так определяется (Vi2)
С>>    void Init(int i, int j)
С>>    {
С>>        m_child.SetData(i);
С>>        p_int = new int[j];
С>>    }; //<-- лишняя точка с запятой (Vi2)
С>>} //<-- нет точки с запятой (Vi2)
Vi2>...
Vi2>

С>>это упрощенный вариант в плане количества переменных- и функций-членов у классов ChildClass и MyClass, но сути это не меняет

Vi2>Наверное, слишком упрощённый вариант. У меня после переделки синтаксических ошибок — всё скомпилировалось

Vi2>Компилятору без разницы — вызываешь ты какую-то функцию перед ошибочно компилируемой строкой или нет.
Vi2>
С>>    myclass.Init(10,10);
С>>    m_Array.Add(myclass); <- если здесь ошибка

С>>//    myclass.Init(10,10);
С>>    m_Array.Add(myclass); <- то здесь она также будет!
Vi2>


ошибок я понаделал конечно много, действительно я их исправил и все скомпилировалось, но зато прога вылетает при добавлении первого элемента в массив

template<class TYPE, class ARG_TYPE>
AFX_INLINE int CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement)
    { int nIndex = m_nSize;
        SetAtGrow(nIndex, newElement);
        return nIndex; }   <- на вот этой строке
Re[5]: Ищи в другом месте
От: Vi2 Удмуртия http://www.adem.ru
Дата: 11.10.02 13:24
Оценка:
Здравствуйте Сергей, Вы писали:

С>ошибок я понаделал конечно много, действительно я их исправил и все скомпилировалось, но зато прога вылетает при добавлении первого элемента в массив

С>template<class TYPE, class ARG_TYPE>
С>AFX_INLINE int CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement)
С>    { int nIndex = m_nSize;
С>        SetAtGrow(nIndex, newElement);
С>        return nIndex; }   <- на вот этой строке

Что тут добавить — CArray просто требует конструктора копирования для классов с нетривиальными данными. Вот и сделай его. И почитай сообщение от Vyacheslav Koltovich.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[6]: Ищи в другом месте
От: Vi2 Удмуртия http://www.adem.ru
Дата: 11.10.02 13:29
Оценка:
Здравствуйте Vi2, Вы писали:

Vi2>Что тут добавить — CArray просто требует конструктора копирования для классов с нетривиальными данными.


Забыл добавить — и оператор присваивания operator= тоже.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[6]: Ищи в другом месте
От: Сергей  
Дата: 11.10.02 15:27
Оценка:
Здравствуйте Vi2, Вы писали:

Vi2>Что тут добавить — CArray просто требует конструктора копирования для классов с нетривиальными данными. Вот и сделай его. И почитай сообщение от Vyacheslav Koltovich.


убираю из объявления и реализации класса(причем только из того, который храню в массиве, но не в тех которые в свою очередь содержаться в нем в качестве переменных-членов — в них как раз таки оставляю) конструктор и деструктор и ошибка пропадает, т.е. добавление элементов в массив происходит без проблем
Re[2]: Как хранить объекты ?
От: Сергей  
Дата: 11.10.02 15:42
Оценка:
Здравствуйте Karamat, Вы писали:


K>Попробуйте использовать массив указателей:

K>Не забудте их удалить после использования

с массивом указателей этой проблемы вроде-бы не возникает
Re[3]: Как хранить объекты ?
От: Сергей  
Дата: 11.10.02 16:05
Оценка:
Здравствуйте Сергей, Вы писали:

С>Здравствуйте Karamat, Вы писали:


С>

K>>Попробуйте использовать массив указателей:
K>>Не забудте их удалить после использования

С>с массивом указателей этой проблемы вроде-бы не возникает


Ошибка нашлась!!!
Всем большое спасибо за то, что помогли, без Ваших ответов я бы искал её гораздо дольше!!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.