неск. имплементаций с разным типом члена данных и м-да
От: Аноним  
Дата: 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.
А>как элегантно разрулить эту ситуацию?

можно конечно добавить в базовый класс абстрактный метод
    virtual void CBaseClass::getData(Destination &dst) = 0;

ну и соответственно во всех выведенных классах:
   template < typename Type, std::string TypeName >
   void CImpl::getData(Destination &dst){
       dst = _value;
   }

но хочется более элегантное решение... т.к. по-прежнему душа хочет писать
Destination dst = pBaseClass->getData();

а не
Destination dst;
pBaseClass->getData(dst);
Re[2]: неск. имплементаций с разным типом члена данных и м-д
От: Erop Россия  
Дата: 09.06.08 17:17
Оценка:
Здравствуйте, Аноним, Вы писали:

А>но хочется более элегантное решение... т.к. по-прежнему душа хочет писать

А как ты планируешь выяснть тип результата?

Я так понял, что ты хочешь написать что-т о такое:
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: неск. имплементаций с разным типом члена данных и м-да
От: Erop Россия  
Дата: 09.06.08 17:19
Оценка:
Здравствуйте, Аноним, Вы писали:

А>как элегантно разрулить эту ситуацию?

Если твоя проблема только в том, чтобы как-то разделить прототипы функций, то можно добавить параметр по умолчанию, например...

Только зачем это всё тебе пока не понятно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: неск. имплементаций с разным типом члена данных и м-д
От: Sashaka Россия  
Дата: 09.06.08 17:27
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


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, но далее возможно и расширять. короче, это я хочу описать интерфейс для работы с классами, представляющими переменные различных типов данных. все что мне нужно — это иметь _единый интерфейс_ для запихивания и получения значений из вышеописанных классов, не обращая внимание на тип собственно самого значения
что-то типа этого
Автор:
Дата: 07.05.04
,хотя еще изучаю этот топик.
E>Можешь привести пример использования такого массива?
массивы пока что вообще не предполагал использовать.
Re[4]: неск. имплементаций с разным типом члена данных и м-д
От: zaufi Земля  
Дата: 09.06.08 17:39
Оценка:
Здравствуйте, Аноним, Вы писали:

А>предполагается "наделять" вышеописанные 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]: неск. имплементаций с разным типом члена данных и м-д
От: StoneWolf Россия http://peter.infosreda.com/ru/
Дата: 19.06.08 21:42
Оценка:
Здравствуйте, Sashaka, Вы писали:

Круто! А возможно сделать подобное, но без 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>бугога.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.