2010-12-13 70 views
7

我知道C++(two?)中的結構和類之間幾乎沒有區別。儘管如此,我已經被指示使用結構來定義簡單的小東西,比如可能不需要成員函數的節點(儘管我可以在技術上包括包含成員函數)。比如我可能會定義一個節點作爲鏈表類的私有成員如下:我可以在沒有定義構造函數的情況下在堆上創建新的結構體嗎?

class LinkedList { 
    struct Node { 
    MyObject *data; 
    Node *next; 
    }; 

    Node *list; 

}; 

在這種情況下,然而,是有可能創造這個結構在堆上的一個新的實例,否則我就需要定義一個構造函數?有沒有辦法在沒有新操作員的情況下在堆上創建事物?或者,更好的是:我是否沒有必要緊緊地堅持這樣一個概念,即不應該爲結構定義成員函數?我應該繼續並定義一個嗎?或者如果我這樣做,是否會像承認Node真的是內部類而不是內部結構?我真的應該爲這些事情擔心嗎?哪個更具可讀性?

謝謝!

回答

5

然而,在這種情況下,是否可以在堆上創建這個結構的新實例,還是我需要定義一個構造函數?有沒有辦法在沒有新操作員的情況下在堆上創建事物?

如前所述,您可以通過new或malloc在堆上創建新實例。

或者更好的是:我沒有必要緊緊地抱住這樣一個概念,即我不應該爲結構定義成員函數嗎?

這是一個更有趣的問題。在C++中,structclass之間的主要(唯一的區別)是 默認訪問說明符。也就是說,struct默認爲公共訪問,class默認爲私有訪問。在我看來,這是決定你們使用哪一種的區別。基本上,如果用戶應該直接訪問成員,那麼它應該是struct

例如,如果您沒有成員函數,那麼顯然意圖是直接訪問對象的成員,因此它將是struct。如果對象只是一個小的專用幫助程序來實現其外部類(如您的示例中所示),那麼即使它具有成員函數,通常也允許外部類訪問其成員等它應該是一個struct。通常使用這些類時,外部類的實現與內部類的實現緊密結合,因此沒有理由將其隱藏起來。因此,對於普通的(如std :: pair)對象或那些使用有限的對象(如私人內部類),對成員的默認訪問可能是件好事,在這些情況下,我會讓它們成爲structs

4

的malloc工作正常:

Node *n = (Node*)malloc(sizeof(*n)); 

只記得free()什麼malloc() 'd和delete什麼new' d。

+1

你應該提到malloc不會運行構造函數,如果有的話。 – 2010-12-13 04:23:32

+0

也免費調用析構函數:) – Arunmu 2010-12-13 04:51:01

+0

並且'calloc'也會做一個'memset(0)' – ruslik 2010-12-13 05:37:45

2

即使你沒有定義構造函數,編譯器會創建一個默認的,所以你可以使用運營商的「新」:

Node *n = new Node; 

AFAIAC,一個結構是一類,除了它的「公開性「違約是顛倒過來的。

+0

但在我的情況下,結構有指針節點:默認的構造函數會使它們指向NULL嗎? – Ziggy 2010-12-13 04:28:46

+0

@Ziggy:不;隱式聲明的默認構造函數將使所有的指針成員不被初始化。如果你想讓它們初始化,你應該聲明你自己的構造函數。 (或者,您可以使用'new'的值初始化形式(也就是'new Node()'))。如果您沒有[良好的C++入門書](http://stackoverflow.com/questions/388242/the-definitive-c++-book-guide-and-list),請考慮獲取一個。 – 2010-12-13 04:39:31

2

但是,在這種情況下,是否可以在堆上創建此結構的新實例,還是需要定義構造函數?

是的,你可以在沒有定義構造函數的情況下在堆上創建它。

有沒有辦法在沒有新操作符的情況下在堆上創建事物?

您可以使用'malloc',並在釋放內存時使用'free'。否則就沒有其他辦法了。

或者更好的是:我沒有必要緊緊地抱住我不應該爲結構定義成員函數的概念嗎?

就個人而言,如果我需要我的結構具有成員函數,我把它改成一個類。我傾向於使用結構,因爲可能會在OCaml中使用記錄。

1

我真的應該擔心這些類型的東西嗎?

是的。正如你所說,結構和類之間確實沒有重要的區別。如果您被告知要製作struct,並且它至少需要一個成員函數,那麼將定義一個成員函數

這真的沒什麼大不了的。

但除此之外,你當然可以堆分配結構沒有構造函數(否則malloc將是毫無意義的C.這語言甚至不已經構造函數)

給出一個struct S,你可以只需撥打new Snew S(),具體取決於您想要的初始化類型。如果你沒有定義一個構造函數,編譯器會爲你製作一個構造函數。

相關問題