Оцените плиз следующий лисапед.
Как положительные так и отрицательные качества.
Планирется Class1Impl сделать закрытым для пользователя (в другом заголовочном файле будет, тут только опережающее объявление оставить),
оставив для пользования только Class1.
class Class1Impl
{
int mA;
int mRefCount;
public:
Class1Impl(): mA(0), mRefCount(1)
{
printf("Class1Impl::Class1Impl()\n");
}
virtual ~Class1Impl()
{
printf("~Class1Impl::Class1Impl()\n");
}
virtual void AddRef()
{
mRefCount++;
}
virtual void Release()
{
mRefCount--;
if (mRefCount <= 0)
delete this;
}
virtual void SetParamAImpl(int a)
{
mA = a;
}
virtual int GetParamAImpl() const
{
return mA;
}
};
class Class1
{
Class1Impl* mInternalImpl;
public:
Class1()
{
mInternalImpl = new Class1Impl;
}
Class1(const Class1& other): mInternalImpl(other.mInternalImpl)
{
if (mInternalImpl)
mInternalImpl->AddRef();
}
virtual ~Class1()
{
if (mInternalImpl)
mInternalImpl->Release();
}
virtual bool operator == (const Class1 & other) const
{
return mInternalImpl == other.mInternalImpl;
}
virtual bool operator != (const Class1 & other) const
{
return mInternalImpl != other.mInternalImpl;
}
virtual Class1 & operator = (const Class1 & other)
{
if (mInternalImpl)
mInternalImpl->Release();
mInternalImpl = other.mInternalImpl;
if (mInternalImpl)
mInternalImpl->AddRef();
return *this;
}
virtual void SetParamA(int a)
{
if (mInternalImpl)
mInternalImpl->SetParamAImpl(a);
}
virtual int GetParamA() const
{
int result = 0;
if (mInternalImpl)
result = mInternalImpl->GetParamAImpl();
return result;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Class1 a;
Class1 b;
Class1 c;
a = c;
printf("abc!\n");
return 0;
}
Здравствуйте, GhostCoders, Вы писали:
GC>Оцените плиз следующий лисапед.
Нихрена не понятно зачем это вообще надо...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, GhostCoders, Вы писали:
GC>Здраствуйте!
GC>Оцените плиз следующий лисапед. GC>Как положительные так и отрицательные качества.
GC>Планирется Class1Impl сделать закрытым для пользователя (в другом заголовочном файле будет, тут только опережающее объявление оставить), GC>оставив для пользования только Class1.
Здравствуйте, GhostCoders, Вы писали:
GC>Здраствуйте!
GC>Оцените плиз следующий лисапед.
"Что это было, Пух?" (с)
Завидую людям, у которых столько свободного времени, что они могут заниматься всякими глупостями, у которых нет ни практической цели, ни вообще какой-либо цели, кроме как "поиспражняться в кодинге".
Здравствуйте, dZentle_man, Вы писали:
Z_>Здравствуйте, GhostCoders, Вы писали:
GC>>Здраствуйте!
GC>>Оцените плиз следующий лисапед. Z_>"Что это было, Пух?" (с) Z_>Завидую людям, у которых столько свободного времени, что они могут заниматься всякими глупостями, у которых нет ни практической цели, ни вообще какой-либо цели, кроме как "поиспражняться в кодинге".
Очевидно же, что студент или что-то типа этого.
Самое время для написания лисапедов.
Здравствуйте, GhostCoders, Вы писали:
GC>Планирется Class1Impl сделать закрытым для пользователя (в другом заголовочном файле будет, тут только опережающее объявление оставить), GC>оставив для пользования только Class1. GC>...
Здравствуйте, dZentle_man, Вы писали:
Z_>Здравствуйте, okman, Вы писали:
O>>1. Оператор присваивания Class1 реализован некорректно, потому что не O>>отрабатывает такую ситуацию: Z_>
Z_>Class1 a;
Z_>a = a;
Z_>
O>>А так вроде все в порядке. Z_>Если уж дотрахиваться до таких мелочей, то надо и на переполнение проверять)
Ничего себе мелочь, UB в результате обычного вызова оператора присваивания. Это же совершенно обычный use-case. А для переполнения счётчика, нужно создать 2^16 объектов являющихся копией друг-друга, что, во-первых, выглядит, мягко говоря, странно, а во-вторых, невозможно (без дополнительных усилий) на машинах с разрядностью менее 64 бит.
O>>>1. Оператор присваивания Class1 реализован некорректно, потому что не O>>>отрабатывает такую ситуацию: Z_>>
Z_>>Class1 a;
Z_>>a = a;
Z_>>
O>>>А так вроде все в порядке. Z_>>Если уж дотрахиваться до таких мелочей, то надо и на переполнение проверять)
KO>Ничего себе мелочь, UB в результате обычного вызова оператора присваивания. Это же совершенно обычный use-case. А для переполнения счётчика, нужно создать 2^16 объектов являющихся копией друг-друга, что, во-первых, выглядит, мягко говоря, странно, а во-вторых, невозможно (без дополнительных усилий) на машинах с разрядностью менее 64 бит.
Это действительно мелочи, в сравнении с тем, что, как говорят китайцы, "а нахуа" вообще этот код?
Здравствуйте, GhostCoders, Вы писали:
GC>а как сейчас поживает эта идиома? Насколько популярна?
Достаточно.
GC>Есть ли в ней смысл?
Если ты задаешь этот вопрос, тебе оно не нужно.
GC>Недостаток я вижу в том, что необходимо вручную дописывать свой враппер для каждого метода.
Недостатков вагон и маленькая тележка.
GC>Хотя можно переопределить -> оператор.
Это дзен которого боятся маги 80-го уровня, а ты пока даже не на 5-м.
Даже не думай!
GC>Для чего это нужно? Хотелось бы иметь умный указатель с подсчетом ссылок, который был бы свободен от следующего бага:
GC> boost::shared_ptr<A> sa(new A()); GC> boost::shared_ptr<A> sb(sa.get()); // Будет двойное удаление A
Это не баг, а непонимание. boost::shared_ptr<A> sb(sa);
Pimpl к умным ссылкам отношение прямого не имеет, он нужен для скрытия реализации.
Здравствуйте, GhostCoders, Вы писали:
GC>Для чего это нужно? Хотелось бы иметь умный указатель с подсчетом ссылок, который был бы свободен от следующего бага:
просто делаешь интрузивный подсчёт ссылок и будет тебе счастье...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, GhostCoders, Вы писали:
GC>Недостаток я вижу в том, что необходимо вручную дописывать свой враппер для каждого метода.
Вообще, это конечно некоторая проблема PImpl в С++.
Но решение ТС ничего в ней не решает.
Есть два известных мне пути.
Путь 1. Описываем общую часть как-то так, что это описание используется ДВАЖДЫ.
Один раз для того, чтобы нагенерить публичную часть интерфейса, а другой раз для того, чтобы нагенерить часть реализации.
// хедер MyClassImpl.hclass MyClass::MyClassimpl {
public:
#include<BeginImpl.h>
#include"MyClass.h"#include<EndImpl.h>
private:
// тут, собственно private часть реализщации
};
Путь 2.
Пишется свой препроцессор, который по как-то размеченному хедеру с описанием реализации генерит хедер с реализацией PImpl- обёртки.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, dZentle_man, Вы писали:
Z_>Здравствуйте, k.o., Вы писали:
Z_>Это действительно мелочи, в сравнении с тем, что, как говорят китайцы, "а нахуа" вообще этот код?
Да ладно, обыкновенный pimpl, что тут непонятного-то? Есть, конечно, проблемы такие как изобретение велосипеда и нарушение SRP, но с кодом вполне можно работать. При необходимости он легко рефакторится до удобоваримого состояния. А вот отлавливать баги вызванные такой реализацией оператора присваивания бывает совсем не весело. В зависимости от везения, проявления могут быть разной степени фееричности. Во всяком случае, эта проблема на порядки отличается от гипотетически возможного переполнения счётчика ссылок.
Z_>>Это действительно мелочи, в сравнении с тем, что, как говорят китайцы, "а нахуа" вообще этот код?
KO>Да ладно, обыкновенный pimpl, что тут непонятного-то? Есть, конечно, проблемы такие как изобретение велосипеда и нарушение SRP, но с кодом вполне можно работать. При необходимости он легко рефакторится до удобоваримого состояния. А вот отлавливать баги вызванные такой реализацией оператора присваивания бывает совсем не весело. В зависимости от везения, проявления могут быть разной степени фееричности. Во всяком случае, эта проблема на порядки отличается от гипотетически возможного переполнения счётчика ссылок.
Лично у меня на второй строчке этого кода забывается что написано на первой. Еще отцы-основателиКерниган с Ритчи на первых же страницах говорили, что переменным и функциям нужно давать как можно более осмысленные имена. Не, ну не как у гугла в его глюгловом движке V8 — название функции в 42 буквы, а 2-3 слова, передающие основную суть, некоторые слова можно даже сократить. Че блин за переменная mA? Мой мозг отказывается такое воспринимать принципиально, это уже признак говнокода — дальше смотреть можно, но нужно ли? Я еще понимаю по работе, когда за это деньги платят, и то повбывав бы, но за просто так себя насиловать? С трудом вынудил себя найти ту же архитектурно заложенную опасность целочисленного переполнения, но целиком анализировать всю идею кода, а тем более просчитывать все возможные ошибки... "На фиг, на фиг — к терапевту" (с) При таком похабном написании в коде еще и ни одного коммента, которые призваны как-то сглаживать проблемы понимания когда ничего больше не помогает. Препод-стайл — "я написал, я такой умный, а вы втыкайте в мои скрижали". Надо иметь какое-то уважение к читателям если хочешь нормальной реакции.