2012-07-03 80 views
1

我有這實際上是指向一個派生類這樣C++通過引用傳遞對象和鑄造

Base *b = new Derived() 

我想知道的基類的一個目的,是有可能通過基類指針通過引用一些可以將對象轉換回Derived類的函數。這樣

Dummy_cast_fn(&b) // casts b to derived class 

什麼叫Dummy_cast_fn後,b應該有派生類(無切片)的完整副本。

編輯 我不明白自指針使用以來沒有切片的部分。我的問題是Derived類從函數調用返回到共享庫,並且我無權訪問Derived的.h文件。我僅有的信息是Derived基於Base類。我有權訪問Base.h,因此我可以實例化一個Base對象,但是當我嘗試訪問在Derived中定義的函數但不在Base中時出現問題。所以我想知道是否可以對基類派生類型進行類型轉換,然後我將能夠訪問在Derived中定義的函數,而不是在Base中。

+0

你想要一個完整的副本,或對原始的引用? – justin

+0

除非您將指針存儲在某處,否則爲什麼您要通過指針?相反,通過引用傳遞... –

+0

我想要Derived的完整副本。 –

回答

3

只要b是一個指針或引用Derived,你總是可以:

  1. 向下投送到Derived
  2. 只要您使用b,就可以將其視爲Base

即,b是什麼決定了它的靜態類型,在這種情況下是Base。但是,由於它實際上指向了Derived,因此可以始終向下轉發它。但是,要將其用作Derived,則必須具有類型爲Derived的變量。

因此,如果Dummy_cast_fn的目的只是爲了解決b中的某些問題 - 這是無用的。如果一個對象被切片,沒有任何東西可以修復它。但在你的情況下,沒有切片,因爲你正在使用指針。

根據問題的編輯編輯:

首先,你Derived對象未切片。讓我們從桌子上拿下。你有一個指向完整的Derived的指針(假設這是你通過的),但是當你使用指針Base時,你只能訪問它的Base部分。現在,你說你沒有Derived的定義。這意味着你將無法向這種類型轉型,因爲編譯器不知道它是如何定義的。沒有鑄造將在這裏工作。如果您沒有Derived的定義,則沒有合法的C++方式可以調用sum函數。

我不明白爲什麼Derived的作者爲您提供了它的文檔而沒有提供它的定義。有了這種多態性,提供者通常會讓用戶擁有一些「接口」,將實際類型留作內部實現細節。如果因爲您沒有定義而無法使用Derived,那麼讓您擁有其文檔沒有意義。

+0

我設法得到了一些關於此的更多信息。整個想法是構建一個插件系統,它可以從共享庫調用插件,而不包含.h文件,因此當系統添加新插件時不需要重新編譯。將插件視爲功能,可以通過解析子目錄列表來添加和加載功能,以查找必須加載哪些功能。所有插件都將基於定義可用的基類。把它看作是類似於用Java或Python導入的東西...... –

+0

@VivekKhurana,這正是爲什麼只提供'Base'的原因。這是插件界面,這是用戶應該知道的唯一一件事。該插件如何提供功能是該插件的業務。如果'sum'方法應該是插件功能的一部分,它應該被添加到'Base'中。請注意,如果導入的類不可用,則Java的導入將不起作用。唯一的區別是在Java中有反射,它可以繞過定義並調查未知類型。你在C++中沒有。 – eran

2

你不能改變一個Base*Derived*,但你可以得到一個Derived*指向一個Base*所指向的對象,使用dynamic_cast

Derived* d = dynamic_cast<Derived*>(b); 
if (d) { 
    // cast was succesful 
} else { 
    // cast failed, 
    // e.g. because b* does not point to a Derived* but some other derived type 
} 
2

你不能改變你的Base* b的類型,你可以創建一個新的指針

Derived* p = static_cast<Derived*>(b); 

並使用它。一旦b被宣佈爲Base*,您無法修改其類型。您也可以使用dynamic_cast,雖然這比較慢並且可能不是必須的(儘管我不能肯定地說 - 這取決於您的要求)。如果您正確使用虛擬功能,你甚至可以不需要做任何造型 - 這是多態

的目的之一