2013-03-28 69 views
4

我想寫的是在一定的層次結構的任何派生類工作的功能,而無需修改抽象類的輸入參數:如何從純抽象基類引用創建對象副本?

class A { 
public: 
    A(int val): m_i(val) { } 
    virtual void add(int i) = 0; 

    int m_i; 
}; 

class B: public A { 
public: 
    B(int val): A(val) { } 
    B(): A(0) { } 
    virtual void add(int i) { m_i += i; } 
}; 

class C: public A { 
public: 
    C(int val): A(val) { } 
    C(): A(0) { } 
    virtual void add(int i) { m_i += i*2; } 
}; 

int f(const A& base_class) 
{ 
    // how to create a concrete copy of class base_class? 
    base_class.add(5); 
} 

這裏F()應爲B和C的工作,但我可以」 t創建具體類的副本,因爲我不知道實際類型,除非使用dynamic_cast。

是否有另一種方法來解決這個問題或應該只使用dynamic_cast?

+0

爲什麼F()需要做一個副本? – andre

+0

請注意,這裏的問題不是關於抽象類,而是一般關於基類的引用。 –

回答

2

俗稱virtual constructor idiom的典型方法是,以限定另一虛擬方法用於克隆具體的類,使其在抽象的基礎虛擬,並調用它根據需要以產生期望的類的實例不知道它的類型:

class A { 
public: 
    A(int val): m_i(val) { } 
    virtual void add(int i) = 0; 
    virtual A* clone() const = 0; // Override in derived classes to return new B/C 
    int m_i; 
}; 
0

從您的問題中不清楚爲什麼您甚至需要複印。

但是,如果你這樣做,你可以有一個clone()方法:

class A { 
public: 
    virtual A* clone() const = 0; 
}; 

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

class C: public A { 
public: 
    virtual C* clone() const { return new(*this); } 
}; 
+0

我需要進行復制,因爲我無法直接修改輸入常量引用。我無法調用該參數的add(),我不能'更改函數簽名。 –

1

的問題是要傳遞const A&add不是const方法,如果你拿走const修改,然後這個工程:

int f(A& base_class) 
{ 
    // how to create a concrete copy of class base_class? 
    base_class.add(5); 

    ///Need a return here 
} 

我使用gcc和真正告訴你是怎麼回事的錯誤是這樣的:

error: no matching function for call to 'A::add(int&) const' 
    base_class.add(a);         ^^^^^ 

no known conversion for implicit 'this' parameter from 'const A*' to 'A*' 
                 ^^^^^^^^ 

根據您的迴應的另一種選擇是讓m_imutable,使成員方法const像這樣:

class A { 
    public: 
    A(int val): m_i(val) { } 
    virtual void add(int i) const = 0; 

    protected: 
    mutable int m_i; 
}; 

class B: public A { 
public: 
    B(int val): A(val) { } 
    B(): A(0) { } 
    virtual void add(int i) const { m_i += i; } 
}; 

class C: public A { 
    public: 
    C(int val): A(val) { } 
    C(): A(0) { } 
    virtual void add(int i) const { m_i += i*2; } 
}; 

int f(const A& base_class) 
{ 
    base_class.add(5) ; 

    //Need a return here 
} 
+0

我不想修改輸入參數。 –

+0

@RobertKubrick'add'突變了這個類,所以你不能把它作爲'const'傳遞並調用'add'。如果你想調用另一個'const'函數,而不是'add',那麼這將起作用。 –

+0

@RobertKubrick,除非你想聲明'm_i'爲'mutable' –