2012-10-11 114 views
2

我有一個巨大的C++代碼庫我正在使用。如何在C++中實例化一個成員變量中的子類實例?

我想介紹一個新的子類,並將其用於各種不同的上下文中,但是我的Java訓練思想在C++中遇到了問題。

我希望儘量減少代碼更改。所以,我感興趣的主要類(下面的BAR)具有類FOO的成員變量。我想製作FOO的子類別FOOSUBCLASS。在java中這是微不足道的。對象默認通過引用存儲。這段代碼沒有這樣做(如下所示),我可以在不改變接口的情況下按摩這些代碼(並且不需要引入引用)並且仍然可以讓我的應用程序工作?

class FOO { 
}; 

class FOOSUBCLASS : FOO { 
public: 
    FOOSUBCLASS(const int id) {_id = id;} 
private: 
    int _id; 
}; 

class BAR { 
public: 
    BAR(const FOO foo) { _foo = foo;} 
private: 
    FOO _foo; 
}; 

下面,是我的主:

FOOSUBCLASS fsc(1); 
BAR b(fsc); 

但是,這並不在VS2005編譯。它說:

「類型轉換」:從「FOOSUBCLASS *」到「常量FOO &」存在轉換,但不能訪問

獲取相同的編譯錯誤,如果我明顯的其它構造函數添加到BAR

BAR(const FOOSUBCLASS foo) { _foo = foo;} 

我對C++的理解是,它會將FOOSUBCLASS中的數據複製到類FOO的對象中。 (使用賦值運算符或類的重寫版本)但在我的情況下,我在FOOSUBCLASS(和一些重寫的​​成員函數)中有額外的成員變量,所以我只是不希望它做到這一點。我希望我的成員變量_foo在某些情況下屬於FOOSUBCLASS類型,在其他情況下爲FOO。這甚至有可能嗎?

感謝您的想法。

+0

'並且沒有介紹參考文獻'爲什麼? –

+0

@JesseGood,因爲我想避免在代碼庫中做出巨大的改變。這是一百萬行代碼庫,引入引用將改變應用程序的生命週期管理。但是,根據下面的答案,它看起來像我完全堅持必須這樣做...... – John

+0

唯一的另一種選擇是添加另一個成員'FOOSUBCLASS myfoosub;'和'BAR(const FOOSUBCLASS)'構造函數。 –

回答

2

你不能像你現在寫的那樣去做,對不起。這被稱爲「切片」,關於它的更多信息可以在這裏找到:What is object slicing?

如果你想要你的_foo成員是多態的,你需要使用一個指針或引用。當你做這樣的事情時,要留意終身管理。

2

使基類公共

class FOOSUBCLASS : public FOO { 
public: 
    FOOSUBCLASS(const int id) {_id = id;} 
private: 
    int _id; 
}; 

而且,當心BAR構造

分配切片的指針/參考,以避免:

class FOO 
{ 
}; 

class FOOSUBCLASS : public FOO 
{ 
public: 
    FOOSUBCLASS(const int id) : _id(id) {} 
private: 
    int _id; 
}; 

class BAR 
{ 
public: 
    BAR(const FOO& foo) : _foo(foo) 
    { 
    } 
private: 
    FOO& _foo; 
}; 

注:我使用的初始化 - 列表語法,而不是構造函數體中的賦值。

+0

關於公共FOO的發現很微妙! – bobestm

+0

公衆FOO讓它編譯,但不處理切片問題,我現在認識到這是「真正」的問題。 – John

+0

@Huh。我的代碼示例處理?我想我發佈了這個「12分鐘前」:) :) – sehe

0

對用戶來說sehe,考慮傳遞一個引用而不是傳值給BAR的構造函數。

class BAR { public: BAR(const FOO& foo) { _foo = foo;} private: const FOO& _foo; };

1

在C首先在默認情況下使用private ++類從它們的基類繼承,這意味着FOOSUBCLASSFOO但轉換爲內部,而不是給你訪問。所以先轉換class FOOSUBCLASS : FOOclass FOOSUBCLASS : public FOO和第二個是Java中的每個這是引用,所以你可以說

FOOSUBCLASS fs; 
FOO f = fs; 

但在C++中,我們有引用和非引用和使用FOO f創建非基準,實際上是一個對象, FOO f = fs只複製FOO部分fsf並且不會導致FOO參考FOOSUBCLASS來實現這一點,您應該使用指針或引用或智能指針。例如,您可以說:

FOOSUBCLASS* fs = new FOOSUBCLASS; 
FOO* f = fs; // Use pointer is OK 
FOO& rf = fs; // A reference of fs as a FOO 
std::auto_ptr<FOO> spf(fs); // OK, but for this destructor must be virtual 
相關問題