想象一下,我有一個Base類和兩個派生自它的類One和Two。在Java中,我可以有以下情形:在C++中實例化派生類型
Base b;
if(condition)
b = new One();
else
b = new Two();
在對象類型在運行時確定(上述目的去堆)。我希望能夠在運行時實例化對象類型 - 我所知道的是它們都共享相同的Base類型 - 但我想保留它的堆棧分配,如下所示:
Base b;
這樣做的最好方法是什麼?
想象一下,我有一個Base類和兩個派生自它的類One和Two。在Java中,我可以有以下情形:在C++中實例化派生類型
Base b;
if(condition)
b = new One();
else
b = new Two();
在對象類型在運行時確定(上述目的去堆)。我希望能夠在運行時實例化對象類型 - 我所知道的是它們都共享相同的Base類型 - 但我想保留它的堆棧分配,如下所示:
Base b;
這樣做的最好方法是什麼?
這樣做的最好方法是什麼?
你不行。如果你聲明一個變量類型爲Base
,那麼它的堆棧分配將適用於持有Base
的實例,但不適用於派生類型的實例(它可能較大,儘管不是,但仍不能完成你的任務問; C++中的變量的運行時類型始終與其聲明的類型相同)。充其量,您可以將slice派生實例轉換爲Base
-類型的變量。
最好的選擇是使用一個指針,可選地包裝在shared_ptr
或unique_ptr
中給你類似的語義。假定所有權沒有被轉移時,該對象在超出範圍時自動銷燬)。
Base* b = (condition) ? (Base *) new One() : new Two();
auto bptr = shared_ptr<Base>(b);
注意,這是什麼讓你實際上是一樣的Java。對象本身是堆分配的,但是對它的引用是堆棧分配的。儘管有語法,但引用類型的Java變量本質上等同於C++中的指針。
爲了在C++中使用繼承,您需要定義一個指針而不是靜態對象,然後使用new
關鍵字對其進行實例化。
實施例:
Base* b;
if(condition)
b = new One();
else
b = new Two();
採取的,例如:
Derived d;
Base* b = &d;
d
是堆棧(自動存儲器)上,但仍然多態性將在b
工作。
如果您沒有基類指針或對派生類的引用,則多態性不起作用,因爲您不再具有派生類。就拿
Base c = Derived();
的c
對象不是Derived
,但Base
,因爲切片。因此,從技術上講,多態性仍然有效,只不過你不再有一個對象來談論。
現在採取
Base* c = new Derived();
c
只是指向內存的某個地方,你真的不關心這是否是實際上是一個Base
或Derived
,但調用的virtual
方法將被動態解析。
所以,看起來,與Java不同,沒有堆分配或指針方式,沒有辦法實現動態綁定。
正如評論說你不能。嗯,你可以但不會運行:
Base &b = *(condition ? (Base *)&One() : (Base *)&Two()); // BROKEN CODE DO NOT USE
(構建使用-fpermissive
,但不這樣做!)
因爲One
& Two
對象是臨時對象。 b
一旦你通過下一行就會無效=>不這樣做(不知道我已經說過了)
以下工作,但不完美:在堆棧上構建兩個對象,所以只有在你可以負擔得起。根據條件只要選擇:
One one;
Two two;
Base &b = *(condition ? (Base *)&one : (Base *)&two);
爲了避免雙重分配,我能想到的在使用方面最接近的事是採取分配的對象的引用(還沒有自動變量,不好意思):
Base &b = *(condition ? (Base *)new One() : (Base *)new Two());
因此,您可以在代碼中使用b
作爲Base
。
你還有如果你想成爲堆棧中分配你的對象與
delete (&b);
對不起,我沒有測試過的唯一代碼:)修復。 –
刪除記憶 - 有沒有(Java不分配堆棧上的對象,所以這2例是不相同)。即使你可以,你的對象也會被[切片](http://stackoverflow.com/questions/274626/what-is-object-slicing)爲「Base」類型。 –
你不能(以任何通知可維護的方式)。它是堆棧分配的,所以它的大小必須在分配時已知。記住在Java中你的對象不是堆棧分配的,所以雖然用C++編寫的Java代碼暗含了堆棧分配,但並不意味着在Java中。 – djgandy
這是經典的XY問題 - http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – Slava