2014-05-06 432 views
0

我有一個指向派生類的指針表。該程序使用了許多使用這些表中的條目的小類。定期地,所有這些小類必須交換,目的是使用表中不同類中的數據,但它們只使用基類數據。所以這些小類使用指向表的條目的指針,但這些指針實際上是指向基類指針的指針。孤立地看,這是這一點,並在GCC 4.8.2以下作品(真實的東西具有複雜的類,這只是一個例子)C++強制指針指向指向基指向指針的指針

#include <iostream> 

class Base {public: int i;}; 
class Derived : public Base {public: int j;}; 

int main() { 

    Base **b; 
    Derived *table[2]; 

    table[0] = new Derived; table[0]->i = 1; table[0]->j = -2; 
    table[1] = new Derived; table[1]->i = 4; table[1]->j = -5; 

    b = reinterpret_cast<Base**>(&(table[0])); 
    std::cout << "first: " << (**b).i << " " << "\n"; 
    b = reinterpret_cast<Base**>(&(table[1])); 
    std::cout << "second: " << (**b).i << " " << "\n"; 

    {Derived *temp; temp = table[0]; table[0] = table[1]; table[1] = temp;} 

    b = reinterpret_cast<Base**>(&(table[0])); 
    std::cout << "first switched: " << (**b).i << " " << "\n"; 
    b = reinterpret_cast<Base**>(&(table[1])); 
    std::cout << "second switched: " << (**b).i << " " << "\n"; 
} 

沒有辦法,該表可以永遠會損壞:它總是將包含指向完全相同的派生類類型的指針,因此理論上它們都可以交換。使用該表的類只會使用基類數據。如果reinterpret_cast被替換爲dynamic_caststatic_cast那麼編譯器會抱怨。現在,這一切都很好,除了這樣的告誡外:「......在大多數情況下,結果是系統特定的代碼,因此是不可移植的」,以及明顯知曉專家的其他真正可怕和嚴厲的陳述很多。

上面是reinterpret_cast的合理安全使用嗎?

+0

'static_cast'也應該可以很好地工作,問題在於你不是簡單地將'Derived *'或'Derived&',而是'Derived **'強制轉換。 –

回答

4

既不安全也不合理。

首先有點咆哮。 reinterpret_cast是一個broadswoard。最後一招的武器。這是不安全的。這不友善。它不會保護你免受你的傷害。它不應該是你選擇的首選工具。如果static_cast不「工作」,並且您不明白編譯器告訴您什麼,那麼您不應該在那裏敲擊reinterpret_cast。相反,你應該第一個試圖理解編譯器的錯誤信息,然後修復實際的問題。

咆哮結束。現在,你的情況:

b = reinterpret_cast<Base**>(&(table[0])); 

table爲指針,TO-Derived的數組。所以你試圖從一個指針指向Derived到一個指針指向Base。你應該做的,而不是被強制轉換的指針,TO-Derived爲指針,TO-Base,像這樣:

Base* b = static_cast<Base*>(table[0]); 

,然後使用它:

std::cout << "first: " << (*b).i << " " << "\n"; 

但由於Derived是嫡系Base,你甚至不需要明確的演員。這會工作得很好:

Base* b = table [0]; 

更妙的是,因爲你並不真的需要一個指針,爲什麼不搶參考呢?

Base& b = *table[0]; 
    std::cout << "first: " << b.i << " " << "\n";