2009-01-08 102 views
41

如果我有一個類如下結構Vs的結構

class Example_Class 
    { 
     private: 
     int x; 
     int y; 
     public: 
     Example_Class() 
     { 
      x = 8; 
      y = 9; 
     } 
     ~Example_Class() 
     { } 
    }; 

而且一個結構如下

struct 
{ 
    int x; 
    int y; 
} example_struct; 

是在example_struct simmilar到的內存結構在Example_Class

例如,如果我這樣做

struct example_struct foo_struct; 
Example_Class foo_class = Example_Class(); 

memcpy(&foo_struct, &foo_class, sizeof(foo_struct)); 

foo_struct.x = 8foo_struct.y = 9(即:與foo_class中的x,y值相同的值)?

我問的原因是我有一個C++庫(不想更改它)與C代碼共享一個對象,我想用一個結構來表示來自C++庫的對象。我只對對象的屬性感興趣。

我知道理想的情況是讓Example_class將C和C++代碼之間的通用結構包起來,但是要改變正在使用的C++庫並不容易。

+5

只是一個小的評論,你的構造函數可以(也有人說應該)寫成這樣:Example_Class():x(8),y(9){} – Dan 2009-01-08 09:11:28

回答

61

C++標準保證是一個C struct的內存佈局和C++ class(或struct - 同只要C++ class/struct符合POD(「普通舊數據」)的標準,它們將是相同的。那麼POD是什麼意思?

類或結構是POD如果:

  • 所有數據成員都是公開的,本身POD或基本類型(但不引用或指針到部件類型),或這些
  • 陣列它不具有用戶定義的構造,賦值運算符或析構函數
  • 它沒有虛函數
  • 它沒有基類

關於唯一允許的「C++ - isms」是非虛擬成員函數,靜態成員和成員函數。

既然你的類有一個構造函數和一個析構函數,它在形式上不是POD類型,所以保證不成立。 (雖然,正如其他人所提到的,實際上,只要沒有虛函數,這兩種佈局在您嘗試的任何編譯器上可能都是相同的)。

有關更多詳細信息,請參閱C++ FAQ Lite的[26.7]節。

10

是在Example_Class

行爲不能保證在example_struct simmilar到的存儲器中的結構,並且是編譯器的依賴性。

話雖如此,但答案是「是的,在我的機器上」,前提是Example_Class不包含虛擬方法(並且不從基類繼承)。

+0

我知道我可能不應該讓我的解決方案取決於架構,但您使用的是什麼機器/編譯器? – hhafez 2009-01-08 01:12:46

+0

微軟的編譯器。 – ChrisW 2009-01-08 01:13:45

+0

在這個例子中有保證。 – fabspro 2012-09-20 10:05:47

7

在你描述的情況下,答案是「可能是」。但是,如果類有任何虛函數(包括可以從基類繼承的虛析構函數),或者使用多繼承,那麼類佈局可能會有所不同。

2

爲了什麼其他人所說的增加(如:編譯器特定的,將有可能只要你沒有虛函數工作):

我會強烈建議靜態斷言(編譯時檢查)如果你正在做這個,sizeof(Example_class)== sizeof(example_struct)。請參見BOOST_STATIC_ASSERT或等效的編譯器特定或自定義構造。如果某人(或某些東西,如編譯器更改)修改該類以使該匹配無效,那麼這是一個很好的第一道防線。如果你想額外檢查,你也可以運行時檢查成員的偏移量是否相同,哪些(和靜態大小斷言一起)將保證正確性。

0

類& C++中的結構是等價的,只是一個結構的所有成員默認都是公共的(類成員默認是私有的)。這可以確保在C++編譯器中編譯遺留的C代碼將按預期工作。

沒有什麼使用在結構中的所有花哨的C++功能阻止你:

struct ReallyAClass 
{ 
    ReallyAClass(); 
    virtual !ReallAClass(); 

    /// etc etc etc 
}; 
0

當你想將數據傳遞給C時,爲什麼不明確地將類的成員分配給結構體?這樣你就知道你的代碼可以在任何地方工作。

-2

您可能只是公開或私下從結構中派生類。然後在C++代碼中正確解析它。

0

在C++編譯器的早期,有一些編譯器首先用類更改struct關鍵字然後編譯的例子。非常相似。

差異來自類繼承,尤其是虛函數。如果類包含虛函數,那麼它的佈局開始時必須有一個指向類型描述符的指針。另外,如果B類繼承自A類,那麼A類的佈局首先出現,然後是B類自己的佈局。

因此,只需將類實例轉換爲結構實例的準確答案是:取決於類的內容。對於具有方法的特定類(構造函數和非虛擬析構函數),佈局可能會相同。如果析構函數被聲明爲虛擬的,那麼結構和類之間的佈局肯定會變得不同。

這是一篇文章這表明沒有太多需要做的從C結構的步驟,以C++類:Lesson 1 - From Structure to Class

這裏是說明虛函數表是如何引入到具有虛擬類文章函數:Lesson 4 - Polymorphism