CTAPOBEP
|
|
« : 12-08-2008 10:15 » |
|
Первое. Шаблон класса. template <class TYPE> class New { TYPE m_pType;
public: New(void) {m_pType=NULL;} New(unsigned int num) {m_pType=(TYPE)new char [sizeof(TYPE)*num];} New(TYPE arg) {*this=arg;} ~New(void) {if (m_pType) delete [] m_pType;} TYPE operator= (TYPE arg) { if (m_pType) delete [] m_pType; return m_pType=arg; } operator TYPE() {return m_pType;} TYPE operator->() {return m_pType;} };
Второе. Как этим пользоваться. Вместо char* ch=new char[num];
пишем
New <char*> ch=new char [num]; //или New <char*> ch(num);
а дальше - все, как обычно:
strcpy(ch, "ABCDEFGH"); ch[8]=0x00;
или
ch="HGFEDCBA\n";
или
ch[0]='A'; ch[1]='B'; ... ch[8]='\0'
if (strcmp(ch, "Abc")) ...
ну и т.д.
Вместо delete [] ch; не пишем ничего, само удалится.
Третье. Все это хорошо, но совсем не интересно. Интересно вот что. class CTestDlg { New <CButton*> m_Button[50]; // Это вместо CButton* m_Button[50]; ...
BOOL CTestDlg::OnInitDialog() { ... for (int i=0; i<50; i++) { m_Button[i]=new CButton; RECT rect={20, 20+i*60, 200, 20+i*60+50}; m_Button[i]->Create("Кнопка", WS_VISIBLE|WS_CHILD, rect, this, 1000+i); } ... }
void CTestDlg::OnDestroy() { // Теперь это не нужно !!! // for (int i=0; i<50; i++) delete m_Button[i]; }
Четвертое. Вопрос. Посмотрите свежим глазом, какие могут быть проблемы при использовании такого класса? Спасибо за внимание.
|
|
« Последнее редактирование: 12-08-2008 11:36 от CTAPOBEP »
|
Записан
|
|
|
|
RXL
Технический
Администратор
Online
Пол:
|
|
« Ответ #1 : 12-08-2008 10:40 » |
|
CTAPOBEP, оберни код тегами [code]...[/code].
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #2 : 12-08-2008 12:10 » |
|
Смотри в нете шаблон "Умные указатели". Тест: ch="HGFEDCBA\n"; Тест не прошел Программа на выполнении упала. printf("%s", ch); Тест не прошел Программа на выполнении упала. ch[0]='a'; Тест не прошел. Программа на выполнении упала. Еше, может быть ситуация, что два разных указателя ссылаются на один и тот же участок памяти. При удалении одного указателя, Второй у тебя станет не валидным. Что приведет к краху программы.
Если интересно, я могу вечером выложить свой велосипед на эту тему.
|
|
« Последнее редактирование: 12-08-2008 12:13 от Finch »
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
CTAPOBEP
|
|
« Ответ #3 : 12-08-2008 12:52 » |
|
ch="HGFEDCBA\n"; Тест не прошел Программа на выполнении упала. printf("%s", ch); Тест не прошел Программа на выполнении упала. ch[0]='a'; Тест не прошел. Программа на выполнении упала. Странно, а у меня все это работает и выдает именно тот результат, какой должен быть. MSVS 6.0 + MFC. Велосипед выкладывай, я люблю велосипеды
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #4 : 12-08-2008 16:37 » |
|
Странно, а у меня все это работает и выдает именно тот результат, какой должен быть.
ты, случаем, не в ДОСе выполняешь ?
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #5 : 12-08-2008 18:48 » |
|
Вот мой велосипед. #include <assert.h> #include <iostream>
template <class T> class smart_ptr { private: struct Tptr { int count; T *ptr; Tptr() { count=1; ptr=NULL; } }; Tptr * ptr; void delete_ptr() { if (ptr != NULL) { ptr->count--; if (ptr->count == 0) { delete ptr->ptr; delete ptr; } ptr=NULL; } }; void new_ptr(T *t) { delete_ptr(); ptr=new Tptr; if (ptr != NULL) ptr->ptr=t; }; void inc_ptr(Tptr *t) { delete_ptr(); ptr=t; if (ptr != NULL) ptr->count++; } public: smart_ptr() {ptr=NULL;}; smart_ptr(T *t) { ptr=NULL; new_ptr(t); }; smart_ptr(const smart_ptr<T> & cl) { ptr=NULL; inc_ptr(cl.ptr); }; ~smart_ptr() { delete_ptr(); }; smart_ptr & operator = (T *t) { if (t != NULL) { new_ptr(t); } return *this; }; smart_ptr & operator = (smart_ptr<T> & cl) { inc_ptr(cl.ptr); return *this; }; T& operator *() { assert(ptr != NULL); assert(ptr->ptr != NULL); return *ptr->ptr; }; T *operator ->() { assert(ptr != NULL); assert(ptr->ptr != NULL); return ptr->ptr; }; T *& get() { assert(ptr != NULL); assert(ptr->ptr != NULL); return ptr->ptr; }; };
int main() { smart_ptr<int> a(new int), b; *a = 123; std::cout << "*a.get() = " << *a << std::endl; b=a; if (a.get() == NULL) std::cout << "As result a.get() is NULL." << std::endl; std::cout << "*b.get() = " << *b.get() << std::endl; return 0;
} [/quote] Делал для своих нужд, поэтому особой функциональности прошу не ожидать :)
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
CTAPOBEP
|
|
« Ответ #6 : 13-08-2008 04:30 » |
|
"ты, случаем, не в ДОСе выполняешь ?" А что это такое ? Вот кусок кода, который у меня прекрасно работает: BOOL CTestDlg::OnInitDialog() { CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon New <char*> ch=new char [9]; strcpy(ch, "ABCDEFGH"); ch[8]=0x00;
AfxMessageBox(ch);
ch="HGFEDCBA\0"; AfxMessageBox(ch);
ch[0]='a'; ch[1]='b'; ch[2]='c'; ch[3]='d'; ch[4]='e'; ch[5]='f'; ch[6]='g'; ch[7]='h'; ch[8]='\0';
AfxMessageBox(ch);
if (!strcmp(ch, "abcdefgh")) AfxMessageBox("Равно !!!"); else AfxMessageBox("Не равно !!!");
return TRUE; // return TRUE unless you set the focus to a control }
Finch, спасибо, есть куда расти Так. Почему меня так мало пинают? Ну вот как в таких условиях код улучшать?
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #7 : 13-08-2008 10:51 » |
|
CTAPOBEP, Может ты не привел полностью код. Но конструкция ch[0]='a'; у тебя явно должна не работать. Так как, ты по крайней мере не переопредели []. У меня стоит компилятор g++ (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21). И на нем при компиляции выскакивают warning. При исполнении программа просто падает.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #8 : 13-08-2008 18:01 » |
|
CTAPOBEP, DOS я имею в виду )
|
|
|
Записан
|
|
|
|
CTAPOBEP
|
|
« Ответ #9 : 14-08-2008 04:39 » |
|
Я привел тот код, который сам добавил, все остальное - дело рук Wizard'a. Вот проект целиком, желающие могут убедиться - http://slil.ru/26057820По поводу непереопределенного оператора [] - есть оператор TYPE, от возвращает указатель, этого должно быть достаточно. "CTAPOBEP, DOS я имею в виду )" А я имею в виду, что даже слова такого не знаю
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #10 : 14-08-2008 05:28 » |
|
поправил код ибо не айс: template <class T> // че-то не люблю я стиль аля VS 6.0 class another_smart_ptr // суть класса { T * pointer_; // так оно надёжней, представь инстанцирование простым интом
public: another_smart_ptr() : pointer_(NULL) {} // пишем на C++ another_smart_ptr(unsigned int num): pointer_(NULL) { pointer_ = new T [num]; } another_smart_ptr(T * arg) { *this = arg; } ~another_smart_ptr(void) {if (pointer_) delete [] pointer_;} T* operator= (T * arg) { if (pointer_) delete [] pointer_; return pointer_ = arg; } operator T*() { return pointer_; } // не очень здорово, слишком не явно operator const T*() const { return pointer_; } // иначе будут грабли в некоторых ситуациях T* operator->() { return pointer_; } };
int _tmain(int argc, _TCHAR* argv[]) {
another_smart_ptr<char> ch = new char[9];
// strcpy(ch, "ABCDEFGH\0"); это хрень " подразумевает завершающий ноль strcpy(ch, "ABCDEFGH\0"); // ch[8]=0x00; и нафига мы его еще раз проставили
//ch = "HGFEDCBA"; а это самое интерестное // подумаем, что тут происходит // тут мы берём и копируем указатель на ВРЕМЕННЫЙ КОНСТАНТНЫЙ ЛОКАЛЬНЫЙ объект // и нам это удаётся :), но компилятор сам решает: где, когда и как // он хранит, создаёт и удаляет объект // у нас есть одна гарантия он доступен пока не завершится operator= strcpy(ch, "HGFEDCBA");
// ну то что его может в любом месте разорвать является следствием // копирования указателя на константу ch[0]='a'; ch[1]='b'; ch[2]='c'; ch[3]='d'; ch[4]='e'; ch[5]='f'; ch[6]='g'; ch[7]='h'; ch[8]='\0';
std::cout << strcmp(ch, "abcdefgh");
return 0; }
|
|
|
Записан
|
Странно всё это....
|
|
|
CTAPOBEP
|
|
« Ответ #11 : 14-08-2008 07:16 » |
|
"тут мы берём и копируем указатель на ВРЕМЕННЫЙ КОНСТАНТНЫЙ ЛОКАЛЬНЫЙ объект"
Согласен, так делать не следует. И вообще - не следует смешивать между собой указатели, объявленные обычным образом и объекты подобного класса.
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #12 : 14-08-2008 08:21 » |
|
CTAPOBEP, честно говоря этот класс кроме, как из праздного любопытства вообще не следовало писать. есть же std::string std::vector<char> std::auto_ptr std::rope boost::scoped_ptr boost::scoped_array boost::shared_ptr boost::shared_array
для чего он нужен? вот честно что он даёт? для чего использовался?
|
|
|
Записан
|
Странно всё это....
|
|
|
Антон (LogRus)
|
|
« Ответ #13 : 14-08-2008 08:46 » |
|
совсем забыл. Еще же есть boost pointer containers работаешь как с вектором, а реально хранишь указатели красота
кстати вопрос, то был, какие проблемы что, то я в коде уже отметил в основном это не явное поведение класса оператор равно делает не, то что ожидаем (лучше reset) не метода передачи владения release константные методы не реализованы нет оператора приведения к bool оператор неявного приведения к *, как не кажется не слишком удачное решение в плане прозрачности восприятия
в общем мне больше по душе интерфейс scoped_prt/shared_prt/auto_ptr
|
|
« Последнее редактирование: 14-08-2008 08:53 от LogRus »
|
Записан
|
Странно всё это....
|
|
|
CTAPOBEP
|
|
« Ответ #14 : 14-08-2008 12:10 » |
|
"кроме, как из праздного любопытства вообще не следовало писать" Герберт Шилдт с тобой определенно не согласен В своей книге "Искусство программирования на С++" он рассматривает целых два варианта подобного класса (и еще немножко касается теории этого вопроса). За информацию - спасибо, беру на заметку.
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #15 : 15-08-2008 07:17 » |
|
Это не он со мной не согласен, это я с ним не согласен. Не будем спорить о полезности изобретения велосипедов каждый проект уникален и требует индивидуального подхода.
|
|
|
Записан
|
Странно всё это....
|
|
|
|