Запретить конструкцию
От: Edge  
Дата: 19.05.05 18:00
Оценка:
Всем привет

Захотелось запретить объявление объекта класса через
...
CClassName obj; //так нельзя
...

При этом мне хочется чтобы можно было использовать только динамическое создание обьекта
...
CClassName *obj = new CClassName; 
...

Причем чтобы ошибки отлавливались при компиляции...

Спасибо за внимание
Re: Запретить конструкцию
От: _nn_  
Дата: 19.05.05 18:23
Оценка:
Здравствуйте, Edge, Вы писали:

E>Всем привет


E>Захотелось запретить объявление объекта класса через

E>
E>...
E>CClassName obj; //так нельзя
E>...
E>

E>При этом мне хочется чтобы можно было использовать только динамическое создание обьекта
E>
E>...
E>CClassName *obj = new CClassName; 
E>...
E>

E>Причем чтобы ошибки отлавливались при компиляции...

E>Спасибо за внимание


Следует объявить конструктор защищенным и предоставить функцию создания объекта динамически :
class a
{
public:
    static a* create() { return new a; }
protected:
    a(){}
};

int main()
{
 a* p = a::create(); // OK
 a x; // Error
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Запретить конструкцию
От: Edge  
Дата: 19.05.05 18:26
Оценка:
Здравствуйте, _nn_, Вы писали:

А new нельзя как-нить переопределить? Я попробовал, но мне сказали, что я пытаюсь получить доступ к конструктору

__>Следует объявить конструктор защищенным и предоставить функцию создания объекта динамически :

__>
__>class a
__>{
__>public:
__>    static a* create() { return new a; }
__>protected:
__>    a(){}
__>};

__>int main()
__>{
__> a* p = a::create(); // OK
__> a x; // Error
__>}
__>
Re: Запретить конструкцию
От: _Winnie Россия C++.freerun
Дата: 19.05.05 18:36
Оценка:
Здравствуйте, Edge, Вы писали:


class CClassName
{
private:
  CClassName() {}
  CClassName(const CClassName &other) {}
  void operator=(const CClassName &other) {}

  friend CClassName *Createtor();
};

CClassName *Createtor()
{
  return new CClassName();
}


Если лень передавать много параметров, могу подсказать как решить эту новую проблему.
Правильно работающая программа — просто частный случай Undefined Behavior
Re[3]: Запретить конструкцию
От: _nn_  
Дата: 19.05.05 18:37
Оценка:
Здравствуйте, Edge, Вы писали:

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


E>А new нельзя как-нить переопределить? Я попробовал, но мне сказали, что я пытаюсь получить доступ к конструктору


Не получится, конструктор защищенный.
А чем плохо создание объекта функцией ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: Запретить конструкцию
От: Edge  
Дата: 19.05.05 18:39
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Не получится, конструктор защищенный.

__>А чем плохо создание объекта функцией ?

Проект сильно менять не хочется... А по рукам дать охота
Re: Запретить конструкцию
От: Alex34 Израиль  
Дата: 19.05.05 19:09
Оценка:
Здравствуйте, Edge, Вы писали:

E>Всем привет


E>Захотелось запретить объявление объекта класса через

E>
E>...
E>CClassName obj; //так нельзя
E>...
E>

E>При этом мне хочется чтобы можно было использовать только динамическое создание обьекта
E>
E>...
E>CClassName *obj = new CClassName; 
E>...
E>

E>Причем чтобы ошибки отлавливались при компиляции...

E>Спасибо за внимание


Ёще один возможный вариант с защищенным конструктором:

class CClassName {
...
private:

CClassName () ;

};

Можно определить класс умного указателя который бы был дружествен
твоему классу и в своем конструкторе динамически создавал объект твоего класса

template< class T>
class CSmartPtr
{
...
CSmartPtr() { pObj = new T;}
...
// Стандартные методы умного указателя
...

T* operator->() const { return pObj;}
private:
T* pObj ;
};

В Исходный класс надо добавить :

class CClassName {

friend class CSmartPtr<CClassName>;
...
private:

CClassName () ;

};
Re[5]: Запретить конструкцию
От: _nn_  
Дата: 19.05.05 19:13
Оценка:
Здравствуйте, Edge, Вы писали:

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


__>>Не получится, конструктор защищенный.

__>>А чем плохо создание объекта функцией ?

E>Проект сильно менять не хочется... А по рукам дать охота


if(_охота_дать_по_рукам)
 _дать_по_рукам();



А может стоить подумать решить проблему другим способом ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Запретить конструкцию
От: MaximE Великобритания  
Дата: 19.05.05 20:29
Оценка: 12 (3) +3
On Thu, 19 May 2005 22:00:30 +0400, Edge <21486@users.rsdn.ru> wrote:

> Всем привет

>
> Захотелось запретить объявление объекта класса через
>
> ...
> CClassName obj; //так нельзя
> ...
>

> При этом мне хочется чтобы можно было использовать только динамическое создание обьекта
>
> ...
> CClassName *obj = new CClassName;
> ...
>

> Причем чтобы ошибки отлавливались при компиляции...

Чтобы запретить создание объекта на стеке сделай деструктор непубличным, в хипе — определи непубличный operator delete для класса.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[2]: Запретить конструкцию
От: ecco Россия  
Дата: 20.05.05 07:42
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Чтобы запретить создание объекта на стеке сделай деструктор непубличным,

и не сможешь удалить объект из хипа...

ME>в хипе — определи непубличный operator delete для класса.

и сможешь создавать и в стеке и в хипе, но из хипа не удалишь,
Re[3]: Запретить конструкцию
От: MaximE Великобритания  
Дата: 20.05.05 08:33
Оценка:
Здравствуйте, ecco, Вы писали:

ME>>Чтобы запретить создание объекта на стеке сделай деструктор непубличным,

E>и не сможешь удалить объект из хипа...

class no_stack
{
    ~no_stack();
public:
    void destroy() { delete this; }
};


ME>>в хипе — определи непубличный operator delete для класса.

E>и сможешь создавать и в стеке и в хипе,

5.3.4/8
A new expression obtains storage for the object by calling an allocation function (3.7.3.1). If the new expression terminates by throwing an exception, it may release storage by calling a deallocation function (3.7.3.2). If the allocated type is a nonarray type, the allocation function s name is operator new and the deallocation function s name is operator delete. If the allocated type is an array type, the allocation function s name is operator new[] and the deallocation function s name is operator delete[]. [Note: an implementation shall provide default definitions for the global allocation functions (3.7.3, 18.4.1.1, 18.4.1.2). A C++ program can provide alternative definitions of these functions (17.4.3.4) and/or classspecific versions (12.5). ]

12.5/8
Access to the deallocation function is checked statically. Hence, even though a different one might actually be executed, the statically visible deallocation function is required to be accessible. [Example: for the call on line //1 above, if B::operator delete() had been private, the delete expression would have been illformed. ]


E>но из хипа не удалишь,


class no_heap
{
    static void operator delete(void*, size_t);
public:
    void destroy() { delete this; }
};
Re[4]: Запретить конструкцию
От: Аноним  
Дата: 20.05.05 14:32
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>class no_stack
ME>{
ME>    ~no_stack();
ME>public:
ME>    void destroy() { delete this; }
ME>};
ME>

Уточню: я имел в виду удаление через глобальный или публичный delete, т.к. человек, начавший тему, как я понял, не хочет менять остальной код.

ME>class no_heap
ME>{
ME>    static void operator delete(void*, size_t);
ME>public:
ME>    void destroy() { delete this; }
ME>};
ME>

То же самое.

Насчёт остального: всё тестил в мсвцшном компилере — работает так как я говорил!
Re[5]: Запретить конструкцию
От: ecco Россия  
Дата: 20.05.05 14:34
Оценка:
Извиняюсь за случайный предыдущий аноним, это запостил я.
Re[4]: Запретить конструкцию
От: ecco Россия  
Дата: 20.05.05 14:52
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>class no_heap
ME>{
ME>    static void operator delete(void*, size_t);
ME>public:
ME>    void destroy() { delete this; }
ME>};
ME>

Дополню свои посты в теме:

class no_heap
{
    static void operator delete(void*, size_t);
public:
    void destroy() { delete this; }
};

int main()
{
    no_heap* p = new no_heap();
    return 0;
}

Компилица на ура !
Re[5]: Запретить конструкцию
От: MaximE Великобритания  
Дата: 20.05.05 15:40
Оценка:
ecco wrote:

[]

>
> class no_heap
> {
>     static void operator delete(void*, size_t);
> public:
>     void destroy() { delete this; }
> };
>
> int main()
> {
>     no_heap* p = new no_heap();
>     return 0;
> }
>

> Компилица на ура !

Добавление пустого конструктора решит проблему.

gcc, видимо, делает такой shortcut: если у класса нет определенного конструктора, то исключение конструктором брошено быть не может, поэтому operator delete access check не делается. Я не уверен, позволен ли такой shortcut стандартом. comeau отказывается компилить этот код в любом случае.

Различное поведение компиляторов возможно связано с тем, что это не распространенная идиома, так как пробема, на мой взгляд, надуманная и в реальном коде я не встречал необходимости запрещать создание объектов на стэке / в хипе.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.