Обычно отвечают "сделай private конструктор и порождающую функцию". Но это pain и bore писать для каждого класса такую функцию. А написать обобщенную невозможно. Но всё гораздо проще. Не нужно обобщенной Create. Сделаем обобщённый Destroy. Всё равно нужно что-то писать, но уже гораздо меньше.
class X
{
private:
virtual ~X() {}
friend void kill<X>(X *x);
};
int main()
{
{
X *p = new X;
kill(p); //OK.
}
{
X x;
//error: `virtual X::~X()' is private
}
}
Правильно работающая программа — просто частный случай Undefined Behavior
Едея не нова . У Майерса в "More effective C++", правило 27, описывается подобный подход с закрытым деструктором, только он предлагает для уничтожения использовать функцию-член, что, ИМХО, более правильно, т.к. не требует никаких внешних функций.
class test
{
~test() {}
public:
void destroy() { delete this; }
};
test t;//errorint main()
{
test t1;//error
test* t2 = new test();//okdelete t2;//error
t2->destroy();//okreturn 0;
}
Здравствуйте, _Winnie, Вы писали:
_W>Обычно отвечают "сделай private конструктор и порождающую функцию". Но это pain и bore писать для каждого класса такую функцию. А написать обобщенную невозможно. Но всё гораздо проще. Не нужно обобщенной Create. Сделаем обобщённый Destroy. Всё равно нужно что-то писать, но уже гораздо меньше.
Приватным конструктор делать не надо, иначе не сможешь делать new, а это в наши планы не входит.
На самом деле, достаточно сделать закрытым деструктор.
Здравствуйте, _Winnie, Вы писали:
_W>Обычно отвечают "сделай private конструктор и порождающую функцию". Но это pain и bore писать для каждого класса такую функцию. А написать обобщенную невозможно. Но всё гораздо проще. Не нужно обобщенной Create. Сделаем обобщённый Destroy. Всё равно нужно что-то писать, но уже гораздо меньше.
А может лучше assert в конструкторе на то, что this не слишком отличается от адреса какой-то переменной на стеке?
Но конечно "ещё более правильный" совет дал Maxim Yegorushkin здесь
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
ME>В то время, когда правильный ответ: "Это нафиг не никому надо, займись лучше делом."
Нет, Maxim Yegorushkin, мы не позволим тебе заставить _Winnie заняться делом.
Ибо в его творениях мировой юмор приобретает гораздо больше, чем теряет программирование.
Здравствуйте, MaximE, Вы писали:
>> Обычно отвечают "сделай private конструктор и порождающую функцию".
ME>В то время, когда правильный ответ: "Это нафиг не никому надо, займись лучше делом."
Максим, а ты действительно считаешь, что это нафиг никому не надо?
Ведь такие вещи как минимум способствуют лучшему пониманию языка
Здравствуйте, _Winnie, Вы писали:
_W>Обычно отвечают "сделай private конструктор и порождающую функцию". Но это pain и bore писать для каждого класса такую функцию. А написать обобщенную невозможно. Но всё гораздо проще. Не нужно обобщенной Create. Сделаем обобщённый Destroy. Всё равно нужно что-то писать, но уже гораздо меньше.
Идея — супер! Пора бы тебе для нее и название подобрать... Вот мой вариант:
(c) _Winnie Fast Antistack Idiom. (WFAI) :)
C++ можно выучить за 21 день! ...если дни — полярные.
Здравствуйте, Alxndr, Вы писали:
A>Здравствуйте, MaximE, Вы писали:
>>> Обычно отвечают "сделай private конструктор и порождающую функцию".
ME>>В то время, когда правильный ответ: "Это нафиг не никому надо, займись лучше делом."
A>Максим, а ты действительно считаешь, что это нафиг никому не надо?
Действительно.
A>Ведь такие вещи как минимум способствуют лучшему пониманию языка
Не отрицаю возможной образовательной ценности, но отрицаю практическую ценность запретов вообще.
К примеру, в Python нет спецификаторов доступа, и ничего — все довольны. А посмотрите в код boost::multi_index, сколько усилий было затрачено на расстановку спецификаторов доступа, сколько макросов совместимости навернуто. А ради чего? Я не могу вспомнить за свою практику случая, когда бы я пытался вызвать непубличную ф-цию boost::multi_index, std::map или какого другого класса.
Зачем запрещать создавать объекты где угодно, зачем запрещать наследовать от своих классов? От всех наивных программистов все равно не защититься.
Здравствуйте, MaximE, Вы писали:
A>>Ведь такие вещи как минимум способствуют лучшему пониманию языка
ME>Не отрицаю возможной образовательной ценности, но отрицаю практическую ценность запретов вообще.
Пардон, а, например, статическая типизация в C++ — это ведь тоже своего рода система запретов?
ME>К примеру, в Python нет спецификаторов доступа, и ничего — все довольны. А посмотрите в код boost::multi_index, сколько усилий было затрачено на расстановку спецификаторов доступа, сколько макросов совместимости навернуто. А ради чего?
Может, ради "защиты от дурака"?
ME>Я не могу вспомнить за свою практику случая, когда бы я пытался вызвать непубличную ф-цию boost::multi_index, std::map или какого другого класса.
Поэтому ты считаешь, что это для всех бесполезно?
ME>Зачем запрещать создавать объекты где угодно, зачем запрещать наследовать от своих классов? От всех наивных программистов все равно не защититься.
Не ты ли недавно рассказывал, что 80% (с цифрой могу соврать) твоих классов являются некопируемыми?
Здравствуйте, MaximE, Вы писали:
ME>А ради чего? Я не могу вспомнить за свою практику случая, когда бы я пытался вызвать непубличную ф-цию boost::multi_index, std::map или какого другого класса.
А как Вы, уважаемый Максим, узнаёте, какую функцию Вам не стоит вызывать ?
Предвосхищу ответ:
1) Из документации;
2) Если правильная архитектура, то "приватные" функции не прийдет в голову вызывать.
Касательно 1) — приходим у выводу что спецификаторы доступа делает код в каком-то смысле самодокументируемым
Касательно 2) — есть контр пример NVI
On Wed, 19 Oct 2005 17:27:54 +0400, Alxndr <14348@users.rsdn.ru> wrote:
> Здравствуйте, MaximE, Вы писали: > > A>>Ведь такие вещи как минимум способствуют лучшему пониманию языка > > ME>Не отрицаю возможной образовательной ценности, но отрицаю практическую ценность запретов вообще. > > Пардон, а, например, статическая типизация в C++ — это ведь тоже своего рода система запретов?
Это полезная вещь, не раз помогала.
[]
> ME>Я не могу вспомнить за свою практику случая, когда бы я пытался вызвать непубличную ф-цию boost::multi_index, std::map или какого другого класса. > > Поэтому ты считаешь, что это для всех бесполезно?
Потому что не знаю людей, кого бы это спасло от бага на этапе компиляции.
> ME>Зачем запрещать создавать объекты где угодно, зачем запрещать наследовать от своих классов? От всех наивных программистов все равно не защититься. > > Не ты ли недавно рассказывал, что 80% (с цифрой могу соврать) твоих классов являются некопируемыми?
Это несколько из другой оперы. В С/С++ нет нотации не-value типа, поэтому приходится ее симулировать хэком с private конструктором копий и оператора присваивания.
On Wed, 19 Oct 2005 17:36:04 +0400, srggal <21794@users.rsdn.ru> wrote:
> Здравствуйте, MaximE, Вы писали: > > ME>А ради чего? Я не могу вспомнить за свою практику случая, когда бы я пытался вызвать непубличную ф-цию boost::multi_index, std::map или какого другого класса. > > А как Вы, уважаемый Максим, узнаёте, какую функцию Вам не стоит вызывать ?
Из кода или комментария.
В том же Python ф-ции, которые не стоит вызывать из пользовательского кода оканчиваются на _. Но если очень хочется вызвать — никто запрещать не будет, caveat emptor.
Здравствуйте, Alxndr, Вы писали:
S>>Касательно 2) — есть контр пример NVI
A>Не вполне понятно, почему NVI — контрпример A>Там private функция замещается, а не вызывается.
ТОнкость этого Архитектурного решения состоит на мой взгляд в том,
что в руках потомках не оказывается способов воспользоваться замещенной функцией, ее использование возможно исключительно в Базовом классе. И именно это отличает NVI от шаблонного метода ( если не ошибаюсь )
Здравствуйте, MaximE, Вы писали:
ME>Из кода или комментария.
ME>В том же Python ф-ции, которые не стоит вызывать из пользовательского кода оканчиваются на _. Но если очень хочется вызвать — никто запрещать не будет, caveat emptor.
Ок, с питоном понятно, вопросов нет, но его Вы привели в качестве примера что эизнь на марсе есть, а как же с С++, что Вы скажете на это:
А как Вы, уважаемый Максим, узнаёте, какую функцию Вам не стоит вызывать ?
Предвосхищу ответ:
1) Из документации;
2) Если правильная архитектура, то "приватные" функции не прийдет в голову вызывать.
Касательно 1) — приходим у выводу что спецификаторы доступа делает код в каком-то смысле самодокументируемым
Касательно 2) — есть контр пример NVI
Здравствуйте, MaximE, Вы писали:
>> Не ты ли недавно рассказывал, что 80% (с цифрой могу соврать) твоих классов являются некопируемыми?
ME>Это несколько из другой оперы. В С/С++ нет нотации не-value типа, поэтому приходится ее симулировать хэком с private конструктором копий и оператора присваивания.
Извини, не понял: что мешает сделать простой комментарий
// Эта структура не должна копироваться!struct MyStruct
{
...
};
Если сильно приспичило — копируй, caveat emptor — в комментарии.
P.S. Я ни в коем случае не хочу тебе "поймать" или еще что-то там — я хочу разобраться и понимать этот язык лучше
Здравствуйте, Alxndr, Вы писали:
A>Здравствуйте, MaximE, Вы писали:
>>> Не ты ли недавно рассказывал, что 80% (с цифрой могу соврать) твоих классов являются некопируемыми?
ME>>Это несколько из другой оперы. В С/С++ нет нотации не-value типа, поэтому приходится ее симулировать хэком с private конструктором копий и оператора присваивания.
A>Извини, не понял: что мешает сделать простой комментарий A>
A>// Эта структура не должна копироваться!
A>struct MyStruct
A>{
A> ...
A>};
A>
A>Если сильно приспичило — копируй, caveat emptor — в комментарии.
A>P.S. Я ни в коем случае не хочу тебе "поймать" или еще что-то там — я хочу разобраться и понимать этот язык лучше
Смотри:
class SomeNonCopyAbleClass;
void Foo( SomeNonCopyAbleClass /*тут должна быть передача параметра по ссылке, но меня эта клавиша сломалась*/qwerty );
Далее, что происходит: в SomeNonCopyAbleClass есть некоторый хендел.... Продолжать надо или уже понятно?