vector < someclass *> List;
/*- - Обработчик нажатия кнопки - */
someclass * recent = new human;
List.push_back(recent);
STL <vector>
делаю так:
Код:
Но вот проблема. когда меняем поле List то меняются все поля. Это не хорошо, как этого избежать?
Из того кода, что ты привел, причина твоей ошибки не ясна. Приведи более расширенный код. Где и как ты меняешь list, как понимаешь, что меняются все поля?
вот код:
Код:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "STL.h"
#include <vector>
using namespace std;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
class human{
public:
char * name;
};
vector <human> list;
human h0,h1;
int i=0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Astr;
char * Cstr;
list.push_back(h0);
list.push_back(h1);
Astr = Edit1->Text;
Cstr = Astr.c_str();
list.name = Cstr;
i++;
}
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "STL.h"
#include <vector>
using namespace std;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
class human{
public:
char * name;
};
vector <human> list;
human h0,h1;
int i=0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Astr;
char * Cstr;
list.push_back(h0);
list.push_back(h1);
Astr = Edit1->Text;
Cstr = Astr.c_str();
list.name = Cstr;
i++;
}
//---------------------------------------------------------------------------
Что получается: при первом нажатии на Buttton1 строка из эдита пишется в list[0].name; При втором нажатии на Buttton1 строка из эдита пишется в list[0].name и list[1].name. Почему? там же веть разные объекты h0 и h1
Упс....не в ту ветку запостил. Это Билдер. Извините
Т.к. этот объект кроме всего прочего является временным, это двойная ошибка.
а если char * name заменить на char name[] ?
Код:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "STL.h"
#include <vector>
using namespace std;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
class human{
public:
char * name;
};
vector <human> list;
human h0,h1;
int i=0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
list.push_back(h0);
list.push_back(h1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if((i < list.size())&&(Edit1->Text.Length()>0))
{
list.name = strdup(Edit1->Text.c_str());
i++;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
for(int j = 0; j<list.size(); j++)
{
delete list[j].name;
}
}
#include <vcl.h>
#pragma hdrstop
#include "STL.h"
#include <vector>
using namespace std;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
class human{
public:
char * name;
};
vector <human> list;
human h0,h1;
int i=0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
list.push_back(h0);
list.push_back(h1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if((i < list.size())&&(Edit1->Text.Length()>0))
{
list.name = strdup(Edit1->Text.c_str());
i++;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
for(int j = 0; j<list.size(); j++)
{
delete list[j].name;
}
}
list.name = Str.c_str();
А Как сделать так чтобы объект создавался и заносился в вектор по нажатию кнопки ?
Код:
class human
{
public:
explicit human(const string& name);
explicit human(const char *pname); //не забудем проверить на NULL
human(const human& hum);
human& operator=(const human& rhs);
string name;
...
};
...
OnBtnClicked()
{
list.push_back(human("Vasya Pupkin"));
}
{
public:
explicit human(const string& name);
explicit human(const char *pname); //не забудем проверить на NULL
human(const human& hum);
human& operator=(const human& rhs);
string name;
...
};
...
OnBtnClicked()
{
list.push_back(human("Vasya Pupkin"));
}
Раз есть TForm - значит используется VCL. Раз есть VCL, значит объявлен класс AnsiString.
Кстати, именно он используется для хранения всех текстовых строк окнонных компонентов, и не существует никаких объективных причин использовать какие-либо другие строковые типы в обработчике интерфейса.
Что за "побитовая копия" ? :)
В данном примере в конструкторе копирования и оператор присваивания определять не нужно. Достаточно и дефолтовых.
В случае с std::string все пройдет отлично, а вот если добавить в human нечто, не имеющее copy-constructor и operator=, то может случиться бяка. Поэтому правило хорошего тона: если нечто используется как элемент STL-контейнера, то лучше объявить copy-constructor и operator=.
Он несколько сбивает с толку. Любой тип имеет конструктор копирования, определенный или дефолтовый. В стандарте нет такого понятия, как bitwise copying.
С тем, что объявлять конструктор копирования и оператор присваивания, так же как и виртуальный деструктор - полезная практика, согласен. Но бывают и исключения.
Конструктор копирования для встроенных типов - именно bitwise copying.
Вот именно, для встроенных типов. А как только мы в качестве типа реализации шаблона подствим структурированный тип (struct или class), то для него будет использоваться поэлементное копирование.
[quote=Green]С тем, что объявлять конструктор копирования и оператор присваивания, так же как и виртуальный деструктор - полезная практика. [/quote]
Оправдано в трёх целях:
1. Когда при отладке требуется отследить создание/удаление объекта.
2. Когда набор полей и свойств объекта не позволяет однозначно определить порядок присваивания - компилятор явно потребует создать его.
3. Когда одно (несколько) полей класса является указателем на объект, который создаётся и удаляется своим владельцем.
А конструктор "human (const char *Name)" вообще лишний.
Код:
// код
human Obj1 = "Указатель на char";
// выглядит как
human Obj2 (string ("Указатель на char"));
human Obj1 = "Указатель на char";
// выглядит как
human Obj2 (string ("Указатель на char"));
Достаточно одного конструктора приведения из типа string.
Оправдано в трёх целях:
[/QUOTE]
Таких целей можно привести ещё множество, поэтому я бы не стал постулировать конкретное количество целей.
[QUOTE=el scorpio]
А конструктор "human (const char *Name)" вообще лишний.
Код:
// код
human Obj1 = "Указатель на char";
// выглядит как
human Obj2 (string ("Указатель на char"));
human Obj1 = "Указатель на char";
// выглядит как
human Obj2 (string ("Указатель на char"));
Достаточно одного конструктора приведения из типа string.
[/QUOTE]
Ты в корне неправ.
human Obj1 = "Указатель на char";
здесь будет вызвано два конструктора: string::string(const char*) и human::human(const char*).
human Obj2 (string ("Указатель на char"));
здесь будет вызваны ТРИ конструктора и один деструктор: string::string(const char*), string::string(const string&), human::human(const string&), string::~string().
Т.о. фрагментируется память, снижается производительность, а про читабельность кода я вообще молчу.
Вот именно, для встроенных типов. А как только мы в качестве типа реализации шаблона подствим структурированный тип (struct или class), то для него будет использоваться поэлементное копирование.
[/QUOTE]
Вообще не понял, к чему это. Элементом же может быть встроенный тип.
human Obj1 = "Указатель на char";
здесь будет вызвано два конструктора: string::string(const char*) и human::human(const char*).
[/QUOTE]
Видимо, имелось в виду human::human(const string&).
Еще string::~string().
[QUOTE=Green]
human Obj2 (string ("Указатель на char"));
здесь будет вызваны ТРИ конструктора и один деструктор: string::string(const char*), string::string(const string&), human::human(const string&), string::~string().[/QUOTE]
Два конструктора. string::string(const string&) лишний.
Что имелось в виду, то и написано: при конструировании экземпляра в первом случае - два конструктора, во втором три конструктора и один деструктор.
Что имелось в виду, то и написано: при конструировании экземпляра в первом случае - два конструктора, во втором три конструктора и один деструктор.[/QUOTE]
Так вроде как речь шла об отсутствии human::human(const char*)? (См. сообщение el scorpio)
Третий конструктор - это тот, что будет вызван внутри human::human(const string&)? Тогда да, три.
Это я к тому, что если для структурированного типа оператор "=" не определён, это не значит, что присваивание выполняется аналогично memcopy. В таком случае будет последовательно вызван оператор "=" для каждогох public свойства
А для не public ? :)
Почему в темах по с++/стл стока флейма всегда, и так мало в темах, ну допустим, про дрова под виннт ? :)
Я сам сталкивался с ситуацией, когда компилятор требовал переопределённый "operator =" для класса.
Имелся класс "Окружность" с множеством свойств типа read = Get_Property_Value, но без модификатора write.
Компилятор не мог создать шаблонный контейнер для массива этих объектов, пока я не описал процесс присваивания вручную.
А что касается "читаемых свойств типа read", то это вообще никакого отношения к C++ не имеет. Это приблуда Borland-а, причем IMHO вредная.