簡體   English   中英

C++ 類或結構與 C 結構的兼容性

[英]C++ Class or Struct compatiblity with C struct

是否可以編寫一個與 C 結構完全兼容的 C++ 類或結構。 從兼容性我的意思是對象的大小和變量的內存位置。 我知道使用*(point*)&pnt甚至(float*)&pnt (在變量是浮點數的不同情況下(float*)&pnt是邪惡的,但考慮到它確實是為了性能而需要的。 每秒使用一百萬次常規類型轉換運算符是不合邏輯的。

拿這個例子

Class Point {
    long x,y;
    Point(long x, long y) {
        this->x=x;
        this->y=y;
    }

    float Distance(Point &point) {
        return ....;
    }
};

C 版本是一個 POD 結構

struct point {
    long x,y;
};

最干凈的方法是從 C 結構繼承:

struct point
{
    long x, y;
};

class Point : public struct point
{
  public:
    Point(long x, long y)
        {    this->x=x; this->y=y; }

    float Distance(Point &point)
        {                return ....;        }
}

C++ 編譯器保證 C 風格的結構點具有與 C 編譯器相同的布局。 C++ 類 Point 為其基類部分繼承了此布局(並且由於它不添加數據或虛擬成員,因此將具有相同的布局)。 指向類 Point 的指針將被轉換為指向 struct point 的指針,而無需進行強制轉換,因為始終支持轉換為基類指針。 因此,您可以使用類 Point 對象並自由地將指向它們的指針傳遞給需要指向 struct point 的指針的 C 函數。

當然,如果已經有定義結構點的C頭文件,那么你可以只包含它而不是重復定義。

是的。

  • 在兩種語言中以相同的順序使用相同的類型
  • 確保該類中沒有任何虛擬內容(這樣您就不會在前面卡住 vtable 指針)
  • 根據所使用的編譯器,您可能需要調整結構打包(通常使用編譯指示)以確保兼容性。

(編輯)

  • 此外,您必須注意使用編譯器檢查 sizeof() 類型。 例如,我遇到過一個編譯器將 short 存儲為 32 位值(大多數情況下將使用 16 位值)。 更常見的情況是 int 在 32 位架構上通常是 32 位,在 64 位架構上通常是 64 位。

POD 適用於 C++。 您可以擁有成員函數。 “C++ 中的 POD 類型是一個聚合類,它只包含 POD 類型作為成員,沒有用戶定義的析構函數,沒有用戶定義的復制賦值運算符,也沒有成員指針類型的非靜態成員”

你應該設計你的 POD 數據結構,讓它們自然對齊,然后它們可以在不同架構上的不同編譯器創建的程序之間傳遞。 自然對齊是任何成員的內存偏移量可以被該成員的大小整除。 IE:浮點數位於可被 4 整除的地址上,雙精度位於可被 8 整除的地址上。如果聲明 char 后跟浮點數,大多數體系結構將填充 3 個字節,但有些體系結構可能會填充 1 個字節。 如果您聲明一個浮點數后跟一個字符,則所有編譯器(我應該為此聲明添加一個源代碼,抱歉)根本不會填充。

C 和 C++ 是不同的語言,但 C++ 的意圖一直是您可以擁有一個以二進制兼容的方式支持這兩種語言的實現。 因為它們是不同的語言,所以它是否真的被支持總是一個編譯器實現細節。 通常,同時提供 C 和 C++ 編譯器(或具有兩種模式的單個編譯器)的供應商確實支持在 C++ 代碼和 C 代碼之間傳遞POD 結構(和指向POD 結構的指針)的完全兼容性。

通常情況下,僅僅具有用戶定義的構造斷保證雖然有時可以將指針傳遞給這樣的一個目的是C函數期待一個指向struct與和相同的數據結構和它的工作。

簡而言之:檢查您的編譯器文檔。

在 C 和 C++ 中使用相同的“結構”。 如果要在C++實現中添加方法,可以繼承struct,只要不添加數據成員或虛函數,大小應該是一樣的。

請注意,如果您有一個空結構體或數據成員是空結構體,則它們在 C 和 C++ 中的大小不同。 在 C 中, sizeof(empty-struct) == 0 雖然在 C99 中,不應該允許空結構(但無論如何都可以作為“編譯器擴展”支持)。 在 C++ 中,sizeof(empty-struct) != 0(典型值為 1)。

除了其他答案之外,我肯定不會將任何訪問說明符(public:、private: 等)放入您的 C++ 類/結構中。 IIRC 允許編譯器根據可見性對成員變量塊重新排序,這樣private: int a; pubic: int b; private: int a; pubic: int b; 可能會交換 a 和 b 輪。 參見例如此鏈接: http : //www.embedded.com/design/218600150?printable=true
我承認對為什么 POD 的定義不包括禁止這種效果感到困惑。

只要你的類沒有表現出一些高級特性,比如增長虛擬的東西,它就應該是幾乎相同的結構。

此外,您可以將Class (無論如何由於大寫而無效)更改為struct而不會造成任何傷害。 除了成員將公開(他們現在是私人的)。

但是現在我想到了您談論的類型轉換……您無法通過轉換指針類型將float轉換為表示相同值的long或反之亦然。 我希望你只是為了移動東西而想要這些指針。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM