1. 程式人生 > >詳解C結構體、C++結構體 和 C++類的區別

詳解C結構體、C++結構體 和 C++類的區別

先來說說C和C++中結構體的不同 a) C語言中的結構體不能為空,否則會報錯 1>d:\myproject\visual studio 2013\projects\myc++\main.c(71): error C2016: C 要求一個結構或聯合至少有一個成員 b) C語言中的結構體只涉及到資料結構,而不涉及到演算法,也就是說在C中資料結構和演算法是分離的。換句話說就是C語言中的結構體只能定義成員變數,但是不能定義成員函式。然而在C++中既可以定義成員變數又可以定義成員函式, C++中的結構體和類體現了資料結構和演算法的結合。 不過雖然C語言的結構體中不能定義成員函式,但是卻可以定義函式指標,不過函式指標本質上不是函式而是指標,所以總的來說C語言中的結構體只是一個複雜資料型別 ,只能定義成員變數,不能定義成員函式,不能用於面向物件程式設計。來看一個函式指標的例子:
int My_Add(int a, int b)
{
    return a + b;
}
int My_Sub(int a, int b)
{
    return a - b;
}
struct  CTest
{
    int(*Add)(int, int); //函式指標
    int(*Sub)(int, int);
};

int main()
{
    struct CTest test;
    int ret = 0;
    test.Add = My_Add;
    test.Sub = My_Sub;
    ret = test.Add(3, 5);
    printf("%d", ret);
}

c) 比如說這個結構體吧:

struct  CTest
{
    char ch;
    int num;
};
int main()
{
    CTest test;
    test.num = 1;
    printf("%d", test.num);
}
這樣在C語言中是編譯不過去的,原因提示未定義識別符號CTest。總的來說就是在C語言中結構體變數定義的時候,若為struct 結構體名 變數名定義的時候,struct不能省略。但是在C++之中則可以省略struct。 再來分析C++中的結構體與類的區別: 先來說說C++中兩者的相同之處: 結構體中也可以包含函式;也可以定義public、private、protected資料成員;定義了結構體之後,可以用結構體名來建立物件。也就是說在C++當中,結構體中可以有成員變數,可以有成員函式,可以從別的類繼承,也可以被別的類繼承,可以有虛擬函式。總的一句話:
class和struct的語法基本相同,從宣告到使用,都很相似,但是struct的約束要比class多,理論上,struct能做到的class都能做到,但class能做到的stuct卻不一定做的到。 再來說說兩者的區別:對於成員訪問許可權以及繼承方式,class中預設的是private,而struct中則是public。class還可以用於表示模板型別,struct則不行。 注意struct是可以繼承與被繼承的,這一點有的人可能忽略了,來看一下struct中的繼承與被繼承:
struct A
{
public:
    A(){};
    virtual void Dynamic()
    {
        cout << "A" << endl;
    }
protected:
    void fun();
private:
    int m_Data;
};

struct B:public A
{
public:
    virtual void Dynamic()
    {
        cout << "B" << endl;
    }
};
int main()
{
    A * pa = new B;
    pa->Dynamic();
}
編譯完全沒有問題。 總結一下就是: 概念:class和struct的語法基本相同,從宣告到使用,都很相似,但是struct的約束要比class多,理論上,struct能做到的class都能做到,但class能做到的stuct卻不一定做的到。 型別:struct是值型別,class是引用型別,因此它們具有所有值型別和引用型別之間的差異。 效率:由於堆疊的執行效率要比堆的執行效率高,但是堆疊資源卻很有限,不適合處理邏輯複雜的大物件,因此struct常用來處理作為基型別對待的小物件,而class來處理某個商業邏輯。 關係:struct不僅能繼承也能被繼承 ,而且可以實現介面,不過Class可以完全擴充套件。內部結構有區別,struct只能新增帶參的建構函式,不能使用abstract和protected等修飾符,不能初始化例項欄位。

拓展部分:再來看一看Java之中類和結構體的區別,來看一個例子:
程式碼:
static void Main(string[] args)
        {
            int strNumberA = 100;
            int strNumberB = strNumberA;//編譯器會先複製strNumberA的值,後賦給strNumberB,會在記憶體的兩個地方儲存值100

            MyVector vA = new MyVector();
            MyVector vB = vA;//引用變數的賦值 賦值操作完成後,兩個變數都指向同一記憶體地址 
            vA.Value = 100;
            Console.WriteLine(vA.Value + "  等於  " + vB.Value);//由於vA和vB指向同一記憶體地址,所以vB.Value的值也為100  
            vB.Value = 200;
            Console.WriteLine(vA.Value + "  等於  " + vB.Value);//同理vA.Value =vB.Value 
             
            MyStruct structA = new MyStruct();
            MyStruct structB = structA; //結構是值型別 賦值操作完成後,兩個結構中的結構資訊一致。注意是“結構中的資訊”一致。 
            structA.Value = 100;
            structB.Value = 200;
            Console.WriteLine(structA.Value + "  不等於  " + structB.Value);//同理vA.Value !=vB.Value 
            Console.Read();
        }
        private class MyVector
        {
            public int Value { get; set; }
        }
        private struct MyStruct
        {
            public int Value;
        }  
 

例子可以看出,值型別變數的賦值操作,僅僅是2個實際資料之間的複製。而引用型別變數的賦值操作,複製的是引用,即記憶體地址,由於賦值後二者都指向同一記憶體地址,所以改變其中一個,另一個也會跟著改變。 結構體引出的問題:上面說到值型別的記憶體不由垃圾回收控制,作用域結束時,值型別會自行釋放,減少了託管堆的壓力,因此具有效能上的優勢。例如,通常 struct比class更高效;而引用型別的記憶體回收,有垃圾回收機制控制。這就引出了關於.NET記憶體中的堆和棧的討論 。

最後做一個小小的總結:
關於 Class效能好還是Struct效能好(換言堆效能好?還是棧效能好?) 那麼什麼時機該用呢 ,比較struct和 class的不同,我使用一下網上的一個牛人總結的比較好的一段話: (1) 在表示諸如點、矩形等主要用來儲存資料的輕量級物件時,首選struct。
(2) 在表示資料量大、邏輯複雜的大物件時,首選class。
(3) 在表現抽象和多級別的物件層次時,class是最佳選擇