2010-12-22 3 views
2

У меня есть класс с двумя полями, которые являются указателями на абстрактный класс. Как я могу написать конструктор копирования, который скопирует данные, указанные с двумя указателями.Проблема с конструктором копирования с классом с полиморфными указателями

Вот класс

class OSGFMenu; 
class OSGFMenuItem; 
typedef void(OSGFMenu::*OSGFMenuCommand)(OSGFMenuItem*); 
typedef int (OSGFMenuItem::*FNMETHOD) (int, char*); 
class OSGFMenuItem: 
    public OSGFDrawableComponent 
{ 
public: 
    OSGFMenuItem(Game& game,OSGFMenu& menu) 
     :OSGFDrawableComponent(game),mMenu(menu),mActive(false) 
    { 
    } 
    OSGFMenuItem(const OSGFMenuItem& menuItem) 
     :OSGFDrawableComponent(menuItem),mMenu(menuItem.mMenu) 
    { 
     Copy(menuItem); 
    } 
    OSGFMenuItem& operator=(const OSGFMenuItem& menuItem) 
    { 
     if(&menuItem != this) 
      Copy(menuItem); 
     return *this; 
    } 
    void SetActive(bool active) 
    { 
     mActive = active; 
    } 
    void Activate() 
    { 
     SetActive(true); 
    } 
    void DeActivate() 
    { 
     SetActive(false); 
    } 
    void SetCommand(OSGFMenuCommand command) 
    { 
     mCommand = command; 
    } 
    virtual void Render()const 
    { 
     if(!mActive) 
      DrawIfNotNull(mDrawData); 
     else 
      if(!DrawIfNotNull(mActiveDrawData)) 
       DrawIfNotNull(mDrawData); 

    } 
    virtual void Update(double dTime) 
    { 
     OSGFDrawableComponent* drawData = 
      dynamic_cast<OSGFDrawableComponent*>(mDrawData); 
     if(drawData) 
      drawData->Update(dTime); 
    } 
    void Invoke() 
    { 
     (mMenu.*mCommand)(this); 
    } 
    ~OSGFMenuItem() 
    { 
     SafeDelete(mDrawData); 
     SafeDelete(mActiveDrawData); 
    } 
protected: 
    void SetDrawData(IDrawable* drawData) 
    { 
     mDrawData = drawData; 
    } 
    void SetActiveDrawData(IDrawable* drawData) 
    { 
     mActiveDrawData = drawData; 
    } 
private: 
    bool DrawIfNotNull(IDrawable* drawData)const 
    { 
     if(!drawData)return false; 
     drawData->Render(); 
     return true; 
    } 
    void Copy(const OSGFMenuItem& menuItem) 
    { 
     mCommand = menuItem.mCommand; 
     *mDrawData = *menuItem.mDrawData; 
     *mActiveDrawData = *menuItem.mActiveDrawData; 
     mActive = menuItem.mActive; 
    } 
    OSGFMenuCommand mCommand; 
    OSGFMenu& mMenu; 
    IDrawable* mDrawData; 
    IDrawable* mActiveDrawData; 
    bool mActive; 
}; 

ответ

2

Если вам нужно скопировать точный тип IDrawable иерархии, я думаю, что ваш единственный шанс добавить Clone() абстрактный метод IDrawable интерфейс.

Его подпись будет

IDrawable* clone() const;

вы можете опустить const, если необходимо изменить объект, на который указывает this.

0

Ваш IDrawable понадобится какая-то виртуальная функция Clone().

2

Для этого вам нужен виртуальный экземпляр копии. Так как он не поддерживается в C++, вы можете имитировать этот эффект, имея виртуальный метод clone. См. What is a "virtual" constructor?.

3

Вопрос заключается в том, нужно ли копировать объекты, на которые указывают полиморфные указатели. Если это так, лучшим вариантом будет предоставление виртуального метода clone() в вашей иерархии классов, которая создаст копию объекта.

struct base { 
    virtual base* clone() = 0; 
    virtual void foo() = 0; 
}; 
struct derived : base { 
    virtual derived* clone() { return new derived(*this); } 
    virtual foo(); 
}; 
class container { 
    base * ptr; 
public: 
    container(base * p) : ptr(p) {} 
    container(container const & lhs) : ptr(lhs.ptr->clone()) 
    {} 
}; 
Смежные вопросы