Как скопировать унаследованный класс из его указателя базового класса без сращивания? - PullRequest
1 голос
/ 21 декабря 2011

У меня возникли проблемы с попыткой создать копию класса из указателя на его базовый класс.Лучше всего проиллюстрировать это на следующем примере:

#include <iostream>
#include <vector>

class Base {
  public:
    Base() { }
    virtual void test() { std::cout << "I am just the base class\n"; }
};

class First : public Base {
  public:
    First() { }
    void test() { std::cout << "This is the First class\n"; }
};

class Second : public Base {
  public:
    Second() { }
    void test() { std::cout << "This is the Second class\n"; }
};

int main() {
  First *f = new First();
  Second *s = new Second();

  // First, I keep a vector of pointers to their base class
  std::vector<Base *> ptrs;
  ptrs.push_back(f);
  ptrs.push_back(s);
  ptrs[0]->test();    // Properly calls the implemented virtual class by inheritor
  ptrs[1]->test();    // Properly calls the implemented virtual class by inheritor

  // Now, I want to *copy* the class without it being spliced to just the base class
  // from the ptrs vector (not from 'f')
  First *f2 = new First(*ptrs[0]);
}

Ошибка, которую я получаю в итоге:

test.cpp: In function ‘int main()’:
test.cpp:35: error: no matching function for call to ‘First::First(Base&)’
test.cpp:12: note: candidates are: First::First()
test.cpp:10: note:                 First::First(const First&)

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

Ответы [ 2 ]

3 голосов
/ 21 декабря 2011

Вы можете сделать это:

First *f2 = 0;
if ( typeid(*ptrs[0]) == typeid(First))
   f2 = new First(*dynamic_cast<First*>(ptrs[0]));

Это должно сработать.

Но лучше использовать виртуальную функцию clone() в базовом классе и реализовать ее в производном классе:

class Base 
{
  public:
    virtual ~Base() { } //virtual destructed added by me!
    virtual Base *clone() = 0;
};

class First : public Base 
{
  public:
    virtual First *clone() { /* implement it */ }  //Covariant return type
};

И

First *f2 = 0;
if ( typeid(*ptrs[0]) == typeid(First))
   f2 = ptrs[0]->clone(); //no need to use new

Следует отметить два момента:

  • Я добавил виртуальный деструктор в базовый класс. См. эту тему , чтобы узнать, почему вам , вероятно, это нужно.
  • Я использовал другой тип возврата для clone() в производном классе. Он называется ковариантный тип возврата .
1 голос
/ 21 декабря 2011
First *fx=(First*)ptrs[0];
First *f2 = new First(*fx); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...