Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Помогите создать класс

1.9K
31 июля 2006 года
SABROG
242 / / 26.01.2006
Хочу создать класс такого типа. Есть класс Price, который должен содержать массив указателей на экземпляры Tables, каждый экземпляр класса в Tables - тоже класс, и называется он Table. Я хочу иметь возможность получать указатели на классы таким же образом, как это делается в ListBox'e, ListView, Memo и т.п. Т.е. таким образом:

Price->Tables->Name

В принципе массивы я собираюсь держать через класс TList. Нужно ли для этого перегружать операции [ ] ? Как это вообще реализовать ?
240
31 июля 2006 года
aks
2.5K / / 14.07.2006
Обращаться напрямую к переменным внутри класса - очень плохая практика. Создай какое то внутреннее хранилище для своих классов, хоть через стандартные списки или другие контейнеры. А в классе Price например перегрузи оператор []:
YourClass &operator[](int index){...}
Внутри которого по индексу извлекаеться из массива/списка или где там хранится объект и возвращается.
Ну или точно так же можно определить методы доступа, например: YourClass getValue(int index){...}
void setValue(int index, YourClass value){...}
Это будет правильно с точки зрения ООП.
Или как вариант можно определить свой итератор.

Тоесть в идеале тогда обращение должно быть например таким: Price->getName();
1.9K
31 июля 2006 года
SABROG
242 / / 26.01.2006
А почему тогда в самом билдере обращение у всех компонентов идет напрямую к переменным (вроде там в классе объявляется __property, я так могу использовать ?).
 
Код:
YourClass &operator[](int index){...}

А тут по подробнее можно ? В заголовочном файле класса это надо прописывать или в реализации (.cpp). Что должно быть в принципе внутри блока {...} ? Просто набор инструкций, которые будут возвращать данные ? И если да, то каким образом, через return ?
---
Нашел такой пример:
Код:
#include <iostream.h>
// Класс с перегруженным оператором [].
class CMyClass{
    int m_arr[4];
public:
    // Перегрузка оператора [].
    int &operator [](int index){
        return m_arr[index];
    }
};
void main(){
    CMyClass w;
    w[0] = 22;
    w[1] = -2;
    cout<<w[0]<<"\n";
    cout<<w[1]<<"\n";
}
240
31 июля 2006 года
aks
2.5K / / 14.07.2006
[QUOTE=SABROG]А почему тогда в самом билдере обращение у всех компонентов идет напрямую к переменным (вроде там в классе объявляется __property, я так могу использовать ?).
[/QUOTE]
Ну это надо у разработчиков билдера спрашивать. По хорошему за такое надо руки отрывать. Хотя у них с помощью __property, как я понимаю определяеться "виртуальные" переменные, которые на самом деле генерируються из методов. Возможно еще для удобства совместимости с другими борландовскими продуктами типа дельфи. В любом случае это вносит путаницу, развращает программиста и противоречит принципам ООП. Так что на мой взгяд так лучше не делать. Особенно если обращаться к данным именно напрямую - это нельзя делать категорически, во избежание собственных же ошибок и для нормального проектирования.

[QUOTE=SABROG]
 
Код:
YourClass &operator[](int index){...}

А тут по подробнее можно ? В заголовочном файле класса это надо прописывать или в реализации (.cpp). Что должно быть в принципе внутри блока {...} ? Просто набор инструкций, которые будут возвращать данные ? И если да, то каким образом, через return ?[/QUOTE]
Ну да - это обычный метод класса, и описываешь его как остальные методы этого класса. Собственно не важно где но если придерживаться стандартов, например если у тебя сам класс описан в хедере YourClass.h
 
Код:
...
class YourClass{
    ...
public:
    StoredClass &operator[](int index);
    ...
};


А реализация в YourClass.cpp
 
Код:
#include "YourClass.h"
    ...
    StoredClass &YourClass::operator[](int index){
           //извлечение нужных данных
           return yourdata;
    }

после этого можно индексированно обращаться к классу, как к обычному массиву напрмиер. Тоесть читать и писать по индексу.
240
31 июля 2006 года
aks
2.5K / / 14.07.2006
Ага, пример у тебя вполне наглядный.
1.9K
31 июля 2006 года
SABROG
242 / / 26.01.2006
Вот встал перед выбором. Использовать ли VCLный класс TList или STL (STLPort?) для хранения указателей на экземпляры классов. Можете пример привести как организовать динамический массив с помощью STL ? Выйграю ли я в скорости при работе с массивами STL ?
240
31 июля 2006 года
aks
2.5K / / 14.07.2006
Если пользоваться STL списком, тогда:
list<StoredClass *> objList; //описание списка содержащего указатели на StoredClass
TList ни разу не исспользовал ибо предпочитаю не пользоваться C Builder-ом.
Хотя если уж говорить об stl::list, то наверно тут более уместно будет stl::vector исспользовать:
 
Код:
vector<StoredClass *> yourClasses;
...
yourClasses.push_back(obj);
...

    StoredClass &YourClass::operator[](int index){
           return yourClasses[index];
    }

В случае нехватки элементов:
yourClasses.resize(newSize);
Как у них с производительностью - не знаю не сравнивал. Но мне так кажеться что по алгоритмы поиска, обращения к данным и т.п. врятли будут ощутимо хуже гдето. Наверняка они одного порядка - иначе смысл делать заведомо проигрышный класс )
1.9K
31 июля 2006 года
SABROG
242 / / 26.01.2006
Ну есть же две функции сортировки: bubles и quicksort (пузырьковая и быстрая), первая заметнее проигрывает. Правда я не знаю, может они для разных задач применимы лучше.

По поводу увеличения размера. Я так и не понял, могу ли я просто добавлять указатели на экз.класса не меняя каждый раз размер листа ?
240
31 июля 2006 года
aks
2.5K / / 14.07.2006
[QUOTE=SABROG]
По поводу увеличения размера. Я так и не понял, могу ли я просто добавлять указатели на экз.класса не меняя каждый раз размер листа ?[/QUOTE]
Если ты про вектор - то это скорее не список, а что то наподобие массива, если так будет понятней. Тоесть заранее можно задать примерный размер который оидается (ну например 2000), и заполнять его. Если же места не будет хватать (заполнили 2000 значений) просто делаем ему resize(...) увеличивая объем.
Впринципе если считаешь, что для работы больше подходит список - возможно. У вектора просто индексация прощще, у списка придеться каждый раз с начала списка бегать.
8.7K
31 июля 2006 года
Rubicon
55 / / 28.10.2005
Цитата:

Ну это надо у разработчиков билдера спрашивать. По хорошему за такое надо руки отрывать. Хотя у них с помощью __property, как я понимаю определяеться "виртуальные" переменные, которые на самом деле генерируються из методов. Возможно еще для удобства совместимости с другими борландовскими продуктами типа дельфи. В любом случае это вносит путаницу, развращает программиста и противоречит принципам ООП. Так что на мой взгяд так лучше не делать. Особенно если обращаться к данным именно напрямую - это нельзя делать


 
Код:
__property <type> <name>={read=Ger_function(), write=Set_function()};

эти методы, фактически, и вызываются, они и пишут/считывают данные их переменной метода, которая, как и методы, должна (желательно) быть private-ной --- нет никаких виртуальных перпеменных!

а про различия вектора и списка посмотри в помощи билдера -- они существенны --- там очень хорошо описано и есть советы, для каких задач какой контейнер лучше применять.
1.9K
31 июля 2006 года
SABROG
242 / / 26.01.2006
А как мне сделать так, чтобы при создании экземпляра класса через new внутри класса автоматически создавались другие классы, тоже через new. Дело в том, что TList нельзя просто объявить как переменную. Его надо создать:
TList *MyList = new TList;

Но этот TList должен быть членом моего класса, поэтому мне не хотелось бы создавать его сначала извне, а потом передавать указатель классу.
1
31 июля 2006 года
kot_
7.3K / / 20.01.2000
[QUOTE=SABROG]А как мне сделать так, чтобы при создании экземпляра класса через new внутри класса автоматически создавались другие классы, тоже через new. Дело в том, что TList нельзя просто объявить как переменную. Его надо создать:
TList *MyList = new TList;

Но этот TList должен быть членом моего класса, поэтому мне не хотелось бы создавать его сначала извне, а потом передавать указатель классу.[/QUOTE]
Используй конструктор или параметры конструктора. В чем проблема то? А поле класса делай указателем на TList.

[QUOTE=aks]Если ты про вектор - то это скорее не список, а что то наподобие массива, если так будет понятней. Тоесть заранее можно задать примерный размер который оидается (ну например 2000), и заполнять его. Если же места не будет хватать (заполнили 2000 значений) просто делаем ему resize(...) увеличивая объем.[/QUOTE]
Вектор сам вполне корректно справляется с добавлением размера - поэтому если логика программы не требует жесткого управления размером массива - лучше предоставить это стандартной библиотеке.
Так же для поиска, сортировки и тому подобного - НЕОБХОДИМО использовать стандартные алгоритмы из STL.
1.9K
31 июля 2006 года
SABROG
242 / / 26.01.2006
Ок. Это я понял. А вот у меня получается, что есть главный класс (обертка), а внутри него конструктор плодит еще несколько классов, которые в свою очередь через конструкторы тоже всего плодят. Если я просто уничтожу первый класс (обертку) через delete сработают ли все остальные деструкторы в подклассах или все что они выделили останется висеть мертвым грузом ?
1
01 августа 2006 года
kot_
7.3K / / 20.01.2000
[QUOTE=SABROG]Ок. Это я понял. А вот у меня получается, что есть главный класс (обертка), а внутри него конструктор плодит еще несколько классов, которые в свою очередь через конструкторы тоже всего плодят. Если я просто уничтожу первый класс (обертку) через delete сработают ли все остальные деструкторы в подклассах или все что они выделили останется висеть мертвым грузом ?[/QUOTE]
Если ты создашь деструктор и в нем очистишь память - то не останется :) Выделением и очисткой памяти управляешь полностью ты - и если память выделяется она должна быть корректно очищена. Деструкторы сработают автоматически если ты используешь объект класса - с указателем это не пройдет.
Есть варианты с использованием auto_ptr - это шаблон основное назначение которого - корректно создавать и удалять указатели на объекты, но я его в работе никогда не использовал - поэтому подсказать тебе особо не могу - думаю воспользовавшись гуглом необходимую информацию найти можно.
1.9K
01 августа 2006 года
SABROG
242 / / 26.01.2006
Спасибо за совет. Теперь, как я понял, мне не нужны даже деструкторы с операциями delete. Для теста написал такие строчки:
 
Код:
#include <memory> // надо добавлять, чтобы класс auto_ptr стал доступен
#include "price_class.cpp" // класс TPrice
#include "xltable_class.cpp" // класс TXLTable

std::auto_ptr<TPrice>Price(new TPrice);
std::auto_ptr<TXLTable>TC(new TXLTable(1,"MyHotel",2,"MyRoom",3,"MyMeal",4,"MyTown",5,"MyStar",6));
Price->Tables->Add((TXLTable *)TC.get());
ShowMessage( ((TXLTable *)Price->Tables->Items[0])->Hotel );

Выводит MessageBox с названием отеля "MyHotel". Вроде работает.

P.S.: немного оффтопика. А нет ли программы какой, которая для форумов генерит bbcode с подстветкой синтаксиса для CPP исходников ? Т.е. не админскую примочку, а пользователькую, чтобы красиво можно было вставить в тэг code содержимое ?
240
01 августа 2006 года
aks
2.5K / / 14.07.2006
По поводу auto_ptr хотел бы предостеречь - при присваивании двух auto_ptr меняются оба. Тоесть у присваемого auto_ptr забирается его внутренний указатель, после чего его нельзя использовать и передаеться тому, которому присваивали. Как бы указвать на один объект может одновременно только один auto_ptr. Собственно по этой же причине его не рекомендуеться использовать в STL-ных контейнерах вроде уже перечисленых stl::list и stl::vector, ибо при применениее любой сортировки, перемещения и прочего - данные придут в негодность. Тоесть тут auto_ptr имеет смысл использовать только для хранения данных не заботясь об удалении но не для изменения. (Собственно я им так вобще не пользуюсь)
Кстати вроде бы такое использование запретили стандартом и некоторые компиляторы уже ругаються при попытки создать контейнер с auto_ptr.
Если же хочеться использовать автоматический умный указатель для таких целей рекомендую boost::shared_ptr из библиотеки boost.
Он собственно полностью повторяет семантику обычного указателя только сам отчищает память когда надо.
1.9K
01 августа 2006 года
SABROG
242 / / 26.01.2006
Не понял о чем ты говоришь. Какое присваивание, можно пример ? Может быть я даже и не буду никуда ничего присваивать и меня это устроит.
240
01 августа 2006 года
aks
2.5K / / 14.07.2006
Цитата:
Не понял о чем ты говоришь. Какое присваивание, можно пример ?


 
Код:
std::auto_ptr<sometype> ptr1(new sometype);
std::auto_ptr<sometype> ptr2(new sometype);
...
ptr1 = ptr2;

В векторе такая операция типа yuorVector = yuorVector[j] или yuorVector = ptr или ptr = yuorVector вполне может быть.
Впринципе shared_ptr для этого хорошо подходит. Как и еще много полезностей из буста.
1.9K
01 августа 2006 года
SABROG
242 / / 26.01.2006
[QUOTE=aks]
 
Код:
std::auto_ptr<sometype> ptr1(new sometype);
std::auto_ptr<sometype> ptr2(new sometype);
...
ptr1 = ptr2;

В векторе такая операция типа yuorVector = yuorVector[j] или yuorVector = ptr вполне может быть.
Впринципе shared_ptr для этого хорошо подходит. Как и еще много полезностей из буста.[/QUOTE]
Я решил использовать TList вместо векторов. В принципе присваиваний у меня не будет, т.к. мне главное заполнить лист указателями на экземляпры класса. А очищаться он будет при уничтожении главного класса или при выходе из программы. Присваивать я ничего не буду. Но за предостерижение спасибо.

Если я правильно понимаю, то причина подобного поведения присваивания в "хозяйстве" (owner). Вот нашел пример:
Код:
// Example 5: Transferring ownership from
    //            one auto_ptr to another
    //
    void f()
    {
      auto_ptr<T> pt1( new T );
      auto_ptr<T> pt2;

      pt1->DoSomething(); // OK

      pt2 = pt1;  // now pt2 owns the pointer,
                  // and pt1 does not

      pt2->DoSomething(); // OK

    } // as we go out of scope, pt2's destructor
      // deletes the pointer, but pt1's does nothing

Т.е. присваивая указатель другому auto_ptr'у - первый перестает быть хозяином указателя и передает это право - второму. Таким образом невозможно использовать указатель из первого "поинтера" (или как его назвать, контейнера ?). Я так понял это поведение связано как раз с обеспечением защиты. Таким образом невозможно скопировать указатель, ему можно только поменять хозяина. А что мешает черзе метод get() получить реальный указатель, впихнуть его в вектора, нужным образом отсортировать, а потом создать уже в нужной последовательности под указатели контейнеры ?
1.9K
01 августа 2006 года
SABROG
242 / / 26.01.2006
Вот захотел немного уйти от VCL хотябы в своем классе. Как в конструкторе объявить вектор, если в нем могут содержаться указатели на разные классы ?
--
Сам же и додумался :)
Сделал как делает TList.
 
Код:
std::vector<void *> Tables;


Плюс явное приведение указателей к классам.

В общем такая красота у меня получилась:
 
Код:
std::auto_ptr<TPrice>Price(new TPrice);
std::auto_ptr<TXLTable>TC(new TXLTable(1,"MyHotel",2,"MyRoom",3,"MyMeal",4,"MyTown",5,"MyStar",6));
Price->Tables.push_back(TC.get());
ShowMessage( ((TXLTable *)Price->Tables[0])->Hotel + " : Count of elements inside vector: " + IntToStr(Price->Tables.size()) );
240
01 августа 2006 года
aks
2.5K / / 14.07.2006
[QUOTE=SABROG]
Т.е. присваивая указатель другому auto_ptr'у - первый перестает быть хозяином указателя и передает это право - второму.
[/QUOTE]
Да, так и есть, тоесть в auto_ptr нет инструментов клонирования/копирования непосредственного объекта. В упомянутом shared_ptr ведеться счетчик ссылок, и возможно получать копии объекта указателя. И при изменении из любой копии указывающий на какие то данные можно к ним доступаться, но удаляються данные только когда удаляться все указывающие на них shared_ptr объекты.

[QUOTE=SABROG]
А что мешает черзе метод get() получить реальный указатель, впихнуть его в вектора, нужным образом отсортировать, а потом создать уже в нужной последовательности под указатели контейнеры ?[/QUOTE]
А смысл тогда использовать auto_ptr, если всеравно в векторе изначально храняться обычные указатели? ))

[QUOTE=SABROG]
Вот захотел немного уйти от VCL хотябы в своем классе. Как в конструкторе объявить вектор, если в нем могут содержаться указатели на разные классы ?
[/QUOTE]
Всмысле STL-ный вектор? Там в шаблоне задаеться как раз конкретный класс. Как вариант отнаследовать все хранимые классы от одного базового и хранить указатель на него или использовать например классы опять из того же буста: boost::any - для хранения любых типов и boost::any_cast - обертку вокруг разных кастов.
240
01 августа 2006 года
aks
2.5K / / 14.07.2006
[QUOTE=SABROG]
Сам же и додумался :)
Сделал как делает TList.
 
Код:
std::vector<void *> Tables;


Плюс явное приведение указателей к классам.[/QUOTE]
Можно попробовать так, только одна проблемма - определить к какому типу приводить)) Все указатели void * - нужно знать какой тип был изначально.
1.9K
01 августа 2006 года
SABROG
242 / / 26.01.2006
[QUOTE=aks]Можно попробовать так, только одна проблемма - определить к какому типу приводить)) Все указатели void * - нужно знать какой тип был изначально.[/QUOTE]
Ну да. Правда для меня это не существенно, т.к. в подобном векторе будут все-равно содержаться классы одного типа. Просто я не хочу привязывать к классу-обертке конкретно какой-то класс, там ведь наверно пойдет заморочка с фриендами и т.п.

По поводу auto_ptr. Мне главное чтобы он сам освобождал указатели, а все остальные операции, это всего лишь манипуляции с сортировкой, расстановкой их в массиве. Что от этого измениться ? Я правда так и не понял, как запихнуть в вектор auto_ptrный указатель, ругается на тип. Если такое вообще возможно.
 
Код:
std::auto_ptr<TXLTable>TC(new TXLTable(1,"MyHotel",2,"MyRoom",3,"MyMeal",4,"MyTown",5,"MyStar",6));
Price->Tables.push_back(TC);

Цитата:
[C++ Error] Unit1.cpp(32): E2285 Could not find a match for '_STL::vector<void *,_STL::allocator<void *> >::push_back(_STL::auto_ptr<TXLTable>)'

1.9K
01 августа 2006 года
SABROG
242 / / 26.01.2006
Возникла проблема. Сделал класс:

price_class.cpp
Код:
#include "price_class.h"
//-------------------------------------------------------------------------
TPrice::TPrice()
{
}
//-------------------------------------------------------------------------
TPrice::~TPrice()
{
}
//-------------------------------------------------------------------------
__int32 TPrice::AddTable(__int32 SpoInc,AnsiString Hotel,__int32 HInc,AnsiString Room,__int32 RInc,AnsiString Meal,__int32 MInc,AnsiString Town,__int32 TInc,AnsiString Star,__int32 SInc)
{
    std::auto_ptr<TATable>tTable(new TATable);
    tTable->FHotel = Hotel;
    tTable->FRoom = Room;
    tTable->FMeal = Meal;
    tTable->FTown = Town;
    tTable->FStar = Star;

    tTable->FSpoInc = SpoInc;
    tTable->FHInc   = HInc;
    tTable->FRInc   = RInc;
    tTable->FMInc   = MInc;
    tTable->FSInc   = SInc;
    Tables.push_back(tTable.get());
    ShowMessage(((TATable *)Tables[0])->FHotel);
    return Tables.size();
}

price_class.h
Код:
class TPrice;
class TPrice
{
private:
std::vector<void *> FTables;
public:
typedef struct ATable
{
  AnsiString FHotel,FRoom,FMeal,FTown,FStar;
  __int32 FSpoInc,FHInc,FRInc,FMInc,FTInc,FSInc;
} TATable;
__property std::vector<void *> Tables = {read=FTables,  write=FTables};

  void SplitOnTables(TList *SqlResult);
  __int32 AddTable(__int32 SpoInc,AnsiString Hotel,__int32 HInc,AnsiString Room,__int32 RInc,AnsiString Meal,__int32 MInc,AnsiString Town,__int32 TInc,AnsiString Star,__int32 SInc);
  TPrice();
  ~TPrice();
};


В программе пишу:
 
Код:
std::auto_ptr<TPrice>Price(new TPrice);
__int32 cnt = Price->AddTable(1,"MyHotel",2,"MyRoom",3,"MyMeal",4,"MyTown",5,"MyStar",6);
ShowMessage( ((TPrice::TATable *)Price->Tables.begin())->FHotel);


Тот MessageBox что внутри класса выводит "MyHotel", а MessageBox что в главной программе также обращаясь выводит мусор. Почему так ?
---

Судя по всему этот auto_ptr толи глючит, толи я с ним работать не умею, толи это его защита от чего-то. Но когда я объект создаю через new то все ок....

Увидел такой текст на одном из сайте:
 
Код:
void f()
{
     auto_ptr pa(new A);
     // деструктор A вызовется автоматически при выходе из f()
}

Т.е. я так понимаю, все что я смогу выделить через методы в классе тут же удаляются после выхода из метода. А значит массив указателей на экземпляры классов будет пустым :((
1.9K
02 августа 2006 года
SABROG
242 / / 26.01.2006
С перегрузкой оператора не выходит. Пишу:
Код:
class TPrice
{
private:
       int m[4];
public:
       TPrice();
int &operator[](int index){
        return m[index];
    }

  ~TPrice();
};

TPrice *Price = new TPrice;
Price[0] = 2; //[color=red]тут выводит ошибку[/color]
ShowMessage(IntToStr(Price[0]));

Получаю ошибки:
Цитата:
[C++ Error] Unit1.cpp(46): E2285 Could not find a match for 'TPrice::operator =(int)'
[C++ Error] Unit1.cpp(47): E2285 Could not find a match for 'IntToStr(TPrice)'


Нафиг ему оператор "=" нужен, если я его не перегружал и хочу, чтобы он работал как ему положено, т.е. пихал в массив данные ?
---
Возможно класс TForm уже перегрузил операцию и поэтому нельзя ее перегрузить снова ? Вроде видел что используют где-то конструкцию using ClassName::operator[]
Только что-то все-равно не получается ничего. Эхх, а как все просто в ассемблере...

240
02 августа 2006 года
aks
2.5K / / 14.07.2006
[QUOTE=SABROG]С перегрузкой оператора не выходит.[/QUOTE]
Тут все просто. Перегружаешь операцию для объекта класса, а пытаешься применить ее к указателю на объект.
Тоесть если бы было объявленно:
TPrice Price;
Тогда можно так писать:
Price[0] = 2;

Если же создаешь указатель на объект:
TPrice *Price = new TPrice;
то надо сначала от указателя взять сам объект, а потом применить индексирование - и все будет работать:
(*Price)[0] = 2;
1.9K
02 августа 2006 года
SABROG
242 / / 26.01.2006
А когда я пишут так:
TPrice Price;
Тут что происходит ? Выполняется конструктор класса ? Что собой будет представлять этот объект Price, тип ?
240
02 августа 2006 года
aks
2.5K / / 14.07.2006
Всмысле что происходит?
Когда пишешь:
int x;
происходит создание переменной x типа int, которая уничтожается при выходе из области видимости (например из метода).
Когда же дело доходит до классав, то класс - это тип, а объект - переменная этого типа.
Тоесть когда пишешь YourClass obj; создается объект класса. Естесственно вызывается нужный конструктор - для того он и служит. Если надо передать какието параметры в конструктор - передаються так:
YourClass obj(10, "hello", param3);
Для одноразового исспользования можно создавать объект даже так: YourClass(10, "hello", param3); =))
При выходе из области видимости в которой он создан объект уничтожается как и любая переменная(прежде вызывается деструктор).

Когда делаешь YourClass *objptr = YourClass(10, "hello", param3);
Объект точно также создается, но только в общей динамической памяти программы и указатель на него прсваивается в objptr; =))
Соответственно все переопределенные операторы применяются к самому объекту, а не указателю. И чтобы получить из указателя объект - служит оператор *
(*objptr) - это уже сам объект на который указывает указатель.
Объекты созданные динамически не уничтожаются сами - надо вручную делать им delete (естественно деструктор тоже вызывается)
Вобще такие вещи надо знать стопроцентно, если хочешь программировать на С++ или даже С - это всетаки основы языка. Так что советую почитать книжки по С++ например Страуструпа - создателя языка.
1.9K
02 августа 2006 года
SABROG
242 / / 26.01.2006
Книжки есть. Просто иногда трудно понять как ведет себя программа при разных объявлениях. Классы для меня темный лес, сколько я не пытался в них вникнуть, всегда почему-то набиваю шишки на простейших вещах.
1.9K
02 августа 2006 года
SABROG
242 / / 26.01.2006
Если снова возвращаться к перегрузке операторов. Оператор [] можно перегрузить только для чтения любых типов и для записи только известных ? Вот мне бы хотелось делать .push_back(i), но как я буду его делать для массива, если я не знаю вызвался ли метод для получения или для записи ? Или мне надо перегружать еще и "=" ?
240
02 августа 2006 года
aks
2.5K / / 14.07.2006
Не совсем понял вопроса.
Если говорить о приведенной реализации оператора [], то он возвращает по индексу ссылку на объект хранимого типа (какой то же определенный тип хранится). А ссылку можно использовать, как для того чтобы получить значение (или вызвать методы в случае объектов), так и для того чтобы записать новое. Оператор =, да тоже неплохо бы перегрузить.
1.9K
02 августа 2006 года
SABROG
242 / / 26.01.2006
[QUOTE=aks]Не совсем понял вопроса.
Если говорить о приведенной реализации оператора [], то он возвращает по индексу ссылку на объект хранимого типа (какой то же определенный тип хранится). А ссылку можно использовать, как для того чтобы получить значение (или вызвать методы в случае объектов), так и для того чтобы записать новое. Оператор =, да тоже неплохо бы перегрузить.[/QUOTE]
У меня массив сделан на основе вектора:
 
Код:
private:
std::vector<TATable *>_Tables;


//оператор перегружен так
TATable* &operator[](int index){
        return _Tables[index];
    }

Так вот не может же выделяться память под новый элемент в векторе, если я буду пихать туда ссылку таким макаром:

 
Код:
(*Price)[0] = MyPtr;


Туда пихать можно только таким образом:
 
Код:
_Tables.push_back(MyPtr);


Т.е. как мне перегрузить оператор [] таким образом, чтобы при чтении из массива вызывался метод _Tables.at(i), а при записи _Tables.push_back(ptrObj)
---
Хотя мне кажется я немного подтупливаю. Не могу же я вектору указать конкретный индекс куда хочу втиснуть объект. Придется наверно метод Add писать.
240
02 августа 2006 года
aks
2.5K / / 14.07.2006
Не совсем понял зачем нужна такая хитрая конструкция, которая по индексу возвращает значение вектора по тому же индексу )) Если честно не вижу в этом всем смысла, и без всего кода походу не пойму )))
По поводу памяти - под хранение элементов вектор память выделяет сам, а хранятся там как я понял указатели. Естественно прежде чем положить в указатель хранимый в векторе какой то другой имеет смысл проинициализировать его полезными данными (выделить память или скопировать)
1.9K
02 августа 2006 года
SABROG
242 / / 26.01.2006
Ладно. Не важно. Сделал метод Add. Теперь такой вопрос, я написал деструктор класса TPrice. Вроде эксепшенов пока не выдает. Если найдете косяк где-то в нем, скажите плиз:
 
Код:
TPrice::~TPrice()
{
std::vector<TATable *>::iterator itVectorData;
        for(itVectorData = Tables.begin(); itVectorData != Tables.end(); itVectorData++)
        {
        delete *(itVectorData);
        }
        Tables.erase();
}


Может вообще отказаться от итераторов и использовать Tables.size() в цикле ?
240
02 августа 2006 года
aks
2.5K / / 14.07.2006
Впринципе все правильно, можно и прямым индексированием с исспользованием size().
Кстати нехорошо переменные с заглавной буквы называть. С заглавной буквы обычно типы, классы называют. А переменные с маленькой. Принято так, ато чтение затрудняет )
1.9K
04 августа 2006 года
SABROG
242 / / 26.01.2006
Странная штука с CheckListBox'ом. Попытался в него добавить элемент через Form1->CheckListBox1->Items->Add(); из своего класса, а приложение при этом крашится с эксепшеном в доступе к памяти. Я не могу использовать компоненты из класса или это глюк такой ?
1
04 августа 2006 года
kot_
7.3K / / 20.01.2000
[QUOTE=SABROG]Странная штука с CheckListBox'ом. Попытался в него добавить элемент через Form1->CheckListBox1->Items->Add(); из своего класса, а приложение при этом крашится с эксепшеном в доступе к памяти. Я не могу использовать компоненты из класса или это глюк такой ?[/QUOTE]
Использовать компоненты тебе никто не запрещает - но при этом необходимо проверять действительность успользуемого указателя.
Скорее всего товое Form1 на самом деле указывает хз знает на что.
1
04 августа 2006 года
kot_
7.3K / / 20.01.2000
Кстати, подобное использование компонентов классов - надругательство над идеей повтороного использования кодов :)
1.9K
05 августа 2006 года
SABROG
242 / / 26.01.2006
[QUOTE=kot_]Кстати, подобное использование компонентов классов - надругательство над идеей повтороного использования кодов :)[/QUOTE]
А как надо :) ? А почему он портиться то ? Из всяких Threadoв нормально юзается.
1
05 августа 2006 года
kot_
7.3K / / 20.01.2000
[QUOTE=SABROG]А как надо :) ? А почему он портиться то ? Из всяких Threadoв нормально юзается.[/QUOTE]
Надо передавать или же указатель на объект с которым планируется работа, или указатель на базовый класс (что то типа Sender). В классе обязательно необходимо проверять указатель на NULL и соответствие класса полученного и класса ожидаемого.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог