簡體   English   中英

復制 c++ 抽象類

[英]copying c++ abstract classes

好的,這里有一些代碼。

#include <iostream>
#include <deque>
using namespace std;
class A
{
public:
    virtual void Execute()
    {
        cout << "Hello from class A" << endl;
    }
};
class B: public A
{
public:
    void Execute()
    {
        cout << "Hello from class B" << endl;
    }
};
void Main()
{
    deque<A *> aclasses = deque<A*>(0);
    deque<A *> aclasses2 = deque<A*>(0);
    A a1 = A();
    B b1 = B();
    aclasses.push_back(&a1);
    aclasses.push_back(&b1);
    aclasses[0]->Execute();
    aclasses[1]->Execute();

    //Now say I want to copy a class from aclasses to aclasses2
    //while perserving it's identity and making it a seperate entity, without
    //knowing the exact type it is.

    aclasses2.push_back(new A(*aclasses[0]));
    aclasses2.push_back(new A(*aclasses[1]));
    //Now my problem show itself
    for each(A * a in aclasses2)
        a->Execute();
    //Execute is called from the original class A both times.

}

現在你可能會說,為什么不把第一個雙端隊列的指針放到第二個雙端隊列中呢? 雖然我可以,但我需要數據是獨立的。 基本上我希望能夠從第一個雙端隊列中克隆項目,同時保留那里的身份並給他們自己的數據。

現在是當前修改版本

#include <iostream>
#include <deque>
using namespace std;
class A
{
public:
    virtual void Execute()
    {
        cout << "Hello from class A" << endl;
    }
    virtual ~A() {}             // don't forget the virtual destructor
    virtual A* clone() const {
       return new A(*this);
    }
};
class B: public A
{
public:
    void Execute()
    {
        cout << "Hello from class B" << endl;
    }
    virtual B* clone() {     // return type is co-variant
       return new B( *this );
    }
};
void MainRUNNER()
{
    deque<A *> aclasses = deque<A*>(0);
    deque<A *> aclasses2 = deque<A*>(0);
    A a1 = A();
    B b1 = B();
    aclasses.push_back(&a1);
    aclasses.push_back(&b1);
    aclasses[0]->Execute();
    aclasses[1]->Execute();

    //Now say I want to copy a class from aclasses to aclasses2
    //while perserving it's identity and making it a seperate entity, without
    //knowing the exact type it is.

    aclasses2.push_back(aclasses[0]->clone());
    aclasses2.push_back(aclasses[1]->clone());
    //Now my problem show itself
    for each(A * a in aclasses2)
        a->Execute();
    //Execute is called from the original class A both times.
}

處理的常見模式是通過基礎 class 中的虛擬clone()方法,該方法將創建適當類型的新 object:

struct base {
    virtual ~base() {}             // don't forget the virtual destructor
    virtual base* clone() const { 
       return new base(*this); 
    }
};
struct derived : base {
    virtual derived* clone() const {     // return type is co-variant
       return new derived( *this );
    }
};
int main() {
   std::auto_ptr<base> b1( new derived );
   std::auto_ptr<base> b2( b1->clone() ); // will create a derived object
}

您需要提供一個虛擬復制構造函數——通常這是一個稱為clone的方法——它在每個 class 中被覆蓋以返回正確的類型:

class A {
    virtual A* clone() {
        return new A();
    }
};

class B : public A {
    void A* clone() {
        return new B();
    }
};

為了復制整個 state,這些方法當然可以任意復雜。

當然,這泄露了相當多的 memory。 使用適當的智能指針而不是原始指針(例如,如果您的編譯器支持std::shared_ptr ,則使用boost::shared_ptr否則)。

你在那里有new A(...)方式。 調用的是A的復制構造函數(由編譯器隱式創建。

你想要的是一個clone方法。 這里 它概括了優秀的C++ 編碼標准書中的適當項目。 下面是最終解決方案的無恥副本,它還展示了一個很好的使用NVI 成語來避免切片問題的方法。

class A {// …
public:
  A* Clone() const {                        // nonvirtual
    A* p = DoClone();
    assert( typeid(*p) == typeid(*this) && "DoClone incorrectly overridden" );
    return p;                                // check DoClone's returned type
  }

protected:
 A( const A& );
 virtual A* DoClone() const = 0;
};

class B : public A { // …
public:
  virtual B* Clone() const {return new B(*this); }

protected:
  B( const B& rhs ) : A( rhs ) {/* … */}
};

更新一點解釋。 克隆的基本思想與這里的其他優秀答案相同。

現在,通過克隆,您有切割對象的危險。 例如,如果從A派生的某些 object 忘記實現自己的clone方法,則對A* a = d->clone()的調用將不會返回完整的D object (假設DA的后代)

NVI 習語說將公共接口與虛擬接口分開。 因此,在此示例中, clonepublic ,但不是virtual 它調用一個protected virtual方法doClone ,該方法執行實際的克隆,並且派生對象也實現了該方法。 由於拆分, clone方法可以驗證克隆的 object 的類型是否與原始 object 的類型匹配。

我認為您將對象(即這些類的實例)混淆了。

您的容器aclasses存儲指向現有對象的指針。 您可以將同一個指針在許多不同的容器中多次推送,這稱為克隆。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM