C ++ Список базовых классов и как определить тип класса - PullRequest
0 голосов
/ 01 марта 2012

У меня есть базовый класс line, у которого есть дочерний класс arc (обратите внимание, что дополнительные классы будут наследоваться от line) ... Мне нужно сохранить список или vector из line объектовэто может быть line или arc.arc имеет дополнительное свойство, которого нет у line.Поэтому, когда я работаю со своими списками или vector из line объектов, как мне определить, является ли объект line или arc?

Я подготовил небольшую примерную программу и добавил в комментарии с псевдокодом пример того, чего я хотел бы достичь.Это вообще возможно?

#include <iostream>
#include <vector>
#include <iterator>

using namespace std;

struct point
{
    double x;
    double y;
};

class line
{
    public:

        point start;
        point end;

};

class arc: public line
{
    public:

        point center;

};


int main( int argc, char* argv[] )
{


    vector<line*> a;
    a.push_back( new line );
    a.push_back( new arc );

    for( vector<line*>::iterator i = a.begin(); i < a.end(); i++ )
    {
        (*i)->start.x = 10;
        (*i)->start.y = 11;
        (*i)->end.x = 101;
        (*i)->end.y = 102;
        //if( type of (*i) is arc ) 
        //{
        //  (i)->center.x = 111;
        //  (i)->center.y = 112;
        // }
    }

    return 0;

}

Ответы [ 3 ]

1 голос
/ 01 марта 2012

В вашем цикле попробуйте это:

arc *ar = dynamic_cast<arc *>(*i);
if ( NULL != ar ) {
 // it's an arc!
}else {
  // it's just a line
}

Сид тоже прав ... используйте вместо этого виртуальные функции. Использование dynamic_cast для простых случаев, таких как это, обычно считается плохим стилем.

1 голос
/ 01 марта 2012
class curve
{
public:
    typedef void * type;

public:
    virtual type rtti() const = 0;
};

#define     
DEFINE_RTTI  \
    public: \
        virtual type rtti() const { return desc(); }        \
    public: \
        inline static type desc() { return &desc; } \

class line : public curve
{
    DEFINE_RTTI;
};

class arc : public curve
{
    DEFINE_RTTI;
};

///////////////////////////////////////////////////////////////////////////////
//  Main program
int main()
{
    arc arc_;
    line line_;

    curve *curve_ = new arc();

    _ASSERT(arc_.rtti() == arc::desc());
    _ASSERT(arc_.rtti() != line::desc());

    _ASSERT(line_.rtti() != arc::desc());
    _ASSERT(line_.rtti() == line::desc());

    return 0;
}

Этот rtti работает внутри одного модуля (exe или dll), если вы хотите использовать его в нескольких модулях, вам нужно создать словарь классов

0 голосов
/ 01 марта 2012

Почему вы должны определить? Если вам абсолютно необходимо, вы можете использовать поле typeid через RTTI. Но обычно, если вы используете виртуальные методы, если ваша программа хорошо спроектирована, вам не нужно знать, что такое класс. Вызов виртуальной функции для ссылки на базовый класс или указателя вызовет метод соответствующего экземпляра в зависимости от того, на что он указывает. В этом весь смысл полиморфизма через иерархию классов.

Но опять же, используйте typeid, если вам абсолютно необходимо знать, к какому классу относится экземпляр.

Кроме того, вы не можете получить доступ к данным производных членов класса через указатели базовых классов. Вы можете говорить только через интерфейс базового класса. в этом весь смысл абстракции. Один из уродливых способов - создать толстый интерфейс, который предоставляет аксессорам / мутаторам эти члены данных в интерфейсе базового класса в виде функций виртуальных членов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...