2014-01-11 60 views
1

請告訴我我是否正確。定義vs宣佈類

當我問到聲明類:

class Foo{ 
    int foo, bar; 
public: 
    Foo(); 
    Foo(int arg1, int arg2); 
    void doSomething(); 
    int returnSomething(); 
    ~Foo(); 
}; 

,但是當我問到定義一個類:

class Foo{ 
    int foo, bar; 
public: 
    Foo(){}; 
    Foo(int arg1, int arg2):foo(arg1),bar(arg2){ 
     //body 
    } 
    void doSomething(){ 
     //body 
    } 
    int returnSomething(){ 
     return 0; 
    }; 
    ~Foo(){ 
    // e.g. free the memory 
    } 
}; 

BTW。我應該把一個初始化列表放在一個聲明或定義中還是兩者都有?

+0

您正在使用內聯方法。只使用他們簡單的東西(例如getters/setters)。否則將它們放在一個.cpp文件中,而不是頭文件 –

+0

@ TomDavies92我的答案顯示了將類的聲明和定義分別拆分爲頭文件和源文件的規範方法。 – Keeler

+0

這裏的術語存在一些混淆。我添加了一個答案,以澄清什麼類的聲明和定義。你的聲明都是定義,因此技術上你可以在被要求「定義一個類」時提供。 – juanchopanza

回答

3

術語中存在一些混淆。一個聲明可以是定義因此,無論你的例子都聲明定義class Foo。類定義是否定義了類的成員是另一回事。你的第一個例子只聲明瞭成員函數並定義了數據成員,而第二個例子定義了所有成員。

這是一類的聲明是不一個類定義:

class Foo; 

3.1聲明和定義basic.def]這是所有佈局。從該子句中選擇最相關的示例:

struct X   // defines X 
{ 
    int x;   // defines non-static data member x 
    static int y; // declares static data member y 
    X() : x(0) {} // defines a constructor of X 
}; 

因此,您可以看到上面的計數是作爲類定義計算的。

我應該把一個初始化列表放在一個聲明或定義或它們兩個?

同樣,這在術語上也存在同樣的混淆。重要的是要注意初始化列表只能在構造函數的定義中。所以一旦你將一個添加到構造函數聲明中,這個聲明也成爲一個定義,並且你需要添加一個正文。

1

請告訴我我是否正確。

第一個是一個聲明和類的定義,以及第二個是兩者的類,成員函數和成員對象聲明和其構件的定義功能。

要只定義成員函數,你可以使用:

<return type> <class_name>::<function_name>(...) {...} 

語法。


我應該把初始化列表的聲明或定義或兩者?

構造函數的初始化列表只能放在函數的定義中。

+0

是的,我知道:)。這僅僅是一個例子。謝謝你的解釋:) – tomdavies

+0

我的理解是這兩個例子都是聲明*和*類的定義(不一定是它的成員)。見** 3.1聲明和定義[basic.def] **。 – juanchopanza

+0

@juanchopanza,當然可以。 – Shoe

0

編輯: @juanchopanza告訴我,我是混淆了術語聲明和定義,所以我輸入了一個不完全正確的整體解釋。我在這裏主要糾正它,所以我不會忘記聲明和定義之間的區別。

您的第一個樣本是一個聲明,第二個樣本是聲明和定義之一。

這兩個示例都定義了Foo。不同的是,在你的第一個文件中,你只是聲明瞭成員函數,但在第二個文件中,實際上是在定義它們。

實際申報Foo的方法是class Foo;。要定義Foo,請使用class Foo { ... };

請注意,定義可以代替聲明,即當您定義X時,您還在聲明它。

以下是聲明和定義通常在實踐中如何跨標頭和源文件對進行分割。

foo。HPP(定義Foo,但只能宣佈其功能)

#ifndef __FOO__ 
#define __FOO__ 

class Foo 
{ 
     int foo, bar; 
    public: 
     Foo(); 
     Foo(int arg1, int arg2); 
     void doSomething(); 
     int returnSomething(); 
     ~Foo(); 
}; 

#endif 

Foo.cpp中(成員函數定義)

#include "foo.h" 

Foo::Foo() 
{ 
} 

Foo::Foo(int arg1, int arg2) : 
    foo(arg1), 
    bar(arg2) 
{ 
    //body 
} 

Foo::~Foo() 
{ 
    // e.g. free the memory 
} 

void Foo::doSomething() 
{ 
    //body 
} 

int Foo::returnSomething() 
{ 
    return 0; 
}; 

這不要緊,(foo.hppfoo.cpp)定義每個特定函數,只要你只定義一次函數即可。請將其定義爲foo.hppfoo.cpp,,但不能同時包含

你在初始化的問題列出

想想看:如果你把一個初始化列表構造函數的聲明,它已成爲這兩個聲明定義。

代替在源文件中定義

Foo::Foo(int arg1, int arg2) : 
    foo(arg1), 
    bar(arg2) 
{ 
    //body 
} 

例如,我可以在報頭中定義的那樣:

class Foo 
{ 
    ... 
    Foo(int arg1, int arg2) : 
     foo(arg1), 
     bar(arg2) 
    { 
     //body 
    } 
    ... 
}; 

唯一的區別是,我沒有使用::,範圍操作符。您不要將ClassName::放在您聲明的函數或定義在類定義內的定義之前,因爲編譯器已經將它們識別爲被定義爲類的範圍。

+0

OP代碼中的兩個例子都是聲明*和*定義。 'Foo類;'是一個聲明,但不是一個定義。 – juanchopanza

+0

@juanchopanza Upvoted你的答案,你絕對是對的。 – Keeler

+0

謝謝。這東西很混亂。他們應該爲既是聲明又定義的事物發明一個詞。 – juanchopanza