неск. имплементаций с разным типом члена данных и м-да
От:
Аноним
Дата:
09.06.08 15:53
Оценка:
здравствуйте.
был бы признателен если бы кто-нибудь натолкнул меня на идею о том, как имплементировать иерархию классов, имеющих единый интерфейс (скажем, CBaseClass), но имеющих лишь одно различие по сути: тип хранимого значения, и тип метода по возвращению этого значения? единый интерфейс необходим для того, чтобы далее корректно работать с std::vector< CBaseClass *> и иметь тем самым возможность единой работы со всеми имплементациями класса CBaseClass.
т.е. хочется что-то в духе:
class CBaseClass{
public:
virtual ~CBaseClass(){};
private:
CBaseClass(){};
}
template < typename Type, std::string TypeName >
class CImpl : public CBaseClass{
public:
virtual ~CImpl(){}
std::string getType() const{
return _type;
}
Type getValue() const{
return _value;
}
protected:
std::string _name; //data's name in string representation
std::string _type; //data's type
Type _value; //data's value
};
но в данном случае получается замкнутый круг -- чтобы через CBaseClass иметь возможность обращаться к Type CImpl::getValue() const; нужно добавить в этот класс метод Type getValue() const; но тогда нужно знать чему равен Type, который мы задаем на стадии параметризирования шаблона объектов класса CImpl.
как элегантно разрулить эту ситуацию?
Re: неск. имплементаций с разным типом члена данных и м-да
От:
Аноним
Дата:
09.06.08 16:14
Оценка:
Здравствуйте, Аноним, Вы писали:
А>здравствуйте. А>был бы признателен если бы кто-нибудь натолкнул меня на идею о том, как имплементировать иерархию классов, имеющих единый интерфейс (скажем, CBaseClass), но имеющих лишь одно различие по сути: тип хранимого значения, и тип метода по возвращению этого значения? единый интерфейс необходим для того, чтобы далее корректно работать с std::vector< CBaseClass *> и иметь тем самым возможность единой работы со всеми имплементациями класса CBaseClass. А>т.е. хочется что-то в духе: А>
А> class CBaseClass{
А> public:
А> virtual ~CBaseClass(){};
А> private:
А> CBaseClass(){};
А> }
А> template < typename Type, std::string TypeName >
А> class CImpl : public CBaseClass{
А> public:
А> virtual ~CImpl(){}
А> std::string getType() const{
А> return _type;
А> }
А> Type getValue() const{
А> return _value;
А> }
А> protected:
А> std::string _name; //data's name in string representation
А> std::string _type; //data's type
А> Type _value; //data's value
А> };
А>
А>но в данном случае получается замкнутый круг -- чтобы через CBaseClass иметь возможность обращаться к Type CImpl::getValue() const; нужно добавить в этот класс метод Type getValue() const; но тогда нужно знать чему равен Type, который мы задаем на стадии параметризирования шаблона объектов класса CImpl. А>как элегантно разрулить эту ситуацию?
можно конечно добавить в базовый класс абстрактный метод
Здравствуйте, Аноним, Вы писали:
А>но хочется более элегантное решение... т.к. по-прежнему душа хочет писать
А как ты планируешь выяснть тип результата?
Я так понял, что ты хочешь написать что-т о такое:
void foo( std::vector<CBaseClass*>& data )
{
for( int i = 0; i < data.size(); i++ ) {
Destignation d = data[i]->GetDst; // Как тут узнать тип Destignation?
}
}
При этом я так понял, что data[0] содержит std::stirng, data[1] содержит int, а data[2] содержит std::vector<CBaseClass*>, например...
Можешь привести рпимер использования такого массива?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: неск. имплементаций с разным типом члена данных и м-да
Здравствуйте, Аноним, Вы писали:
А>как элегантно разрулить эту ситуацию?
Если твоя проблема только в том, чтобы как-то разделить прототипы функций, то можно добавить параметр по умолчанию, например...
Только зачем это всё тебе пока не понятно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: неск. имплементаций с разным типом члена данных и м-д
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
struct BasePoly
{
virtual ~BasePoly() =0
{ }
};
template<typename T>
struct PolyT : BasePoly
{
PolyT(T t)
: m_T(t)
{ }
T GetT()
{
return m_T;
}
private:
T m_T;
};
template<class T>
struct AccessorT
{
static T GetT( BasePoly* p )
{
PolyT<T>* pPoly = dynamic_cast< PolyT<T>* >(p);
if (!pPoly)
throw"hihi";
return pPoly->GetT();
}
};
using namespace std;
std::vector<BasePoly*> vec;
vec.push_back( new PolyT<int>(1) );
vec.push_back( new PolyT<double>(2.2) );
vec.push_back( new PolyT<bool>(false) );
int i = AccessorT<int>::GetT( vec[0] );
double d = AccessorT<double>::GetT( vec[1] );
bool b = AccessorT<bool>::GetT( vec[2] );
try
{
char c = AccessorT<char>::GetT( vec[1] );
}
catch(const char* c)
{
cout<<c;
}
бугога.
Re[3]: неск. имплементаций с разным типом члена данных и м-д
От:
Аноним
Дата:
09.06.08 17:34
Оценка:
Здравствуйте, Erop, Вы писали:
E>А как ты планируешь выяснть тип результата?
E>Я так понял, что ты хочешь написать что-т о такое:
void foo( std::vector<CBaseClass*>& data )
E>{
E> for( int i = 0; i < data.size(); i++ ) {
E> Destignation d = data[i]->GetDst; // Как тут узнать тип Destignation?
E> }
E>}
нет, не совсем. E>При этом я так понял, что data[0] содержит std::string, data[1] содержит int, а data[2] содержит E>std::vector<CBaseClass*>, например...
предполагается "наделять" вышеописанные CBaseClass* только значениями типов bool, int, float, но далее возможно и расширять. короче, это я хочу описать интерфейс для работы с классами, представляющими переменные различных типов данных. все что мне нужно — это иметь _единый интерфейс_ для запихивания и получения значений из вышеописанных классов, не обращая внимание на тип собственно самого значения
что-то типа этого
Здравствуйте, Аноним, Вы писали:
А>предполагается "наделять" вышеописанные CBaseClass* только значениями типов bool, int, float, но далее возможно и расширять. короче, это я хочу описать интерфейс для работы с классами, представляющими переменные различных типов данных. все что мне нужно — это иметь _единый интерфейс_ для запихивания и получения значений из вышеописанных классов, не обращая внимание на тип собственно самого значения
boost::variant тебе в помощь
Re[5]: неск. имплементаций с разным типом члена данных и м-д
От:
Аноним
Дата:
09.06.08 20:42
Оценка:
Sashaka, именно это мне и нужно было! zaufi, не отказался бы от наглядного примера. с бустом только знакомлюсь.
Re[5]: неск. имплементаций с разным типом члена данных и м-д
От:
Аноним
Дата:
13.06.08 19:10
Оценка:
Здравствуйте, zaufi, Вы писали:
Z>boost::variant тебе в помощь
не откажусь от примерчика с применением boost::variant.
Re[3]: неск. имплементаций с разным типом члена данных и м-д
Круто! А возможно сделать подобное, но без dynamic_cast? У меня просто есть кусок кода куда можно "воткнуть" похожее, но он очень часто вызывается и боюсь, что dynamic_cast будет "подтормаживать".
S>template<class T> S>struct AccessorT S>{ S> static T GetT( BasePoly* p ) S> { S> PolyT<T>* pPoly = dynamic_cast< PolyT<T>* >(p); S> if (!pPoly) S> throw "hihi"; S> return pPoly->GetT(); S> } S>};
S> using namespace std;
S> std::vector<BasePoly*> vec;
S> vec.push_back( new PolyT<int>(1) ); S> vec.push_back( new PolyT<double>(2.2) ); S> vec.push_back( new PolyT<bool>(false) );
S> int i = AccessorT<int>::GetT( vec[0] ); S> double d = AccessorT<double>::GetT( vec[1] ); S> bool b = AccessorT<bool>::GetT( vec[2] );
S> try S> { S> char c = AccessorT<char>::GetT( vec[1] ); S> } S> catch(const char* c) S> { S> cout<<c; S> }
S>[/ccode]
S>бугога.