получить тип подкласса через указатель базового класса - PullRequest
2 голосов
/ 29 марта 2011

Учитывая макет класса (Base-> Derived; Base-> Derived2) и тот факт, что я держу экземпляр для производных классов в качестве указателя базового класса (Base* baseder2 = new Derived2), я хотел бы иметь возможность создавать экземпляры экземпляр TemplClass с производным типом (что-то вроде sh = new TemplClass<Derived2>(baseder2)). Код ниже создает экземпляры sh = new TemplClass<Base>(baseder2), что приводит к ошибке компиляции из-за того, что fn function не объявлен в классе Base. Как я могу узнать производный тип указателя baseder2, желательно без dynamic_cast? Реальный код имеет множество потомков Base, поэтому я бы хотел избежать операторов if с dynamic_cast. Я искал boost :: type_traits, но, честно говоря, не знаю, что с этим делать. Функция шаблона template <typename T> BaseTemplClass* foo(T* t) - просто слабое оправдание фабричному объекту.

С наилучшими пожеланиями, додол

class Base
{
public:
  virtual ~Base(){}
};

class Derived : public Base
{
public:
  virtual ~Derived(){}
  void function()
  {
    std::cout<<"This is Derived"<<std::endl;
  }
};

class Derived2 : public Base
{
public:
  virtual ~Derived2(){}
   void function()
  {
    std::cout<<"This is Derived2"<<std::endl;
  }
};

class BaseTemplClass
{
public:
  virtual void Print() =0;
};

template <class Tmodel>
class TemplClass : public BaseTemplClass
{
public:
  TemplClass(Tmodel* m)
  {
    model = m;
  }
  void Print()
  {
    model->function();
    std::cout << " TemplClass"<<typeid(model).name() << std::endl;
  }
  Tmodel *model;
};

template <typename T> BaseTemplClass* foo(T* t)
{
  BaseTemplClass* sh;
  std::cout << "FOO: "<<typeid(t).name() << std::endl;
  sh = new TemplClass<T>(t);
  return sh;
}


int main(int argc, char **argv) 
{
    Derived* der = new Derived;
    Derived2* der2 = new Derived2;
    Base* baseder2 = new Derived2;

    BaseTemplClass* sh = foo(der);
    sh->Print();
    delete sh;

    sh = foo(der2);
    sh->Print();
    delete sh;


    sh = foo(baseder2);
    sh->Print();
    delete sh;

    delete der;
    delete der2;
    delete baseder2;
    return 0;
}

Ответы [ 3 ]

4 голосов
/ 29 марта 2011

Имеет ли смысл сделать function абстрактным в Base, чтобы не нужно знать, какой это производный класс?

2 голосов
/ 29 марта 2011

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

1 голос
/ 29 марта 2011

Действительно ли шаблонный класс действительно нужен в вашей ситуации? В приведенном примере вы можете добавить метод «function» в базовый класс и сделать его виртуальным.

Но если вам все еще нужны классы шаблонов, возможно следующее:

class Base
{
public:
  virtual ~Base(){}
  virtual BaseTemplClass* createTemplClass() = 0;
};

class Derived : public Base
{
public:
  virtual ~Derived(){}
  void function()
  {
    std::cout<<"This is Derived"<<std::endl;
  }
  virtual BaseTemplClass* createTemplClass()
  {
    return new TemplClass<Derived>( this );
  }
};

class Derived2 : public Base
{
public:
  virtual ~Derived2(){}
  void function()
  {
    std::cout<<"This is Derived2"<<std::endl;
  }
  virtual BaseTemplClass* createTemplClass()
  {
    return new TemplClass<Derived2>( this );
  }
};


template <typename T> BaseTemplClass* foo(Base* t)
{
  BaseTemplClass* sh;
  std::cout << "FOO: "<<typeid(t).name() << std::endl;
  sh = t->createTemplClass();
  return sh;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...