请告诉我,我是否正确。
当我被要求声明一个班级时:
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
}
};
顺便说一句。我应该在声明或定义中或两者中放置初始化列表吗?
答案 0 :(得分: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 :(得分:1)
请告诉我,我是否正确。
第一个是类的声明和定义,第二个是类的声明,成员函数和成员对象以及其成员函数的定义。
要仅定义成员函数,可以使用:
<return type> <class_name>::<function_name>(...) {...}
语法。
我应该在声明或定义中或两者中放置初始化列表吗?
构造函数的初始化列表应该只放在函数的定义中。
答案 2 :(得分:0)
编辑: @juanchopanza告诉我,我对术语声明和定义感到困惑,所以我输入了一个不完全正确的解释。我在这里纠正它,所以我不会忘记声明和定义之间的区别。
您的第一个样本是声明,第二个是声明和定义。
您的两个示例都定义了Foo
。不同之处在于,在第一个文件中,您只是声明成员函数,但在第二个文件中,您实际上是在定义它们。
声明Foo
的实际方法是class Foo;
。要定义Foo
使用class Foo { ... };
。
请注意,定义可以替换声明,即在您定义X时,您也会声明它。
以下是在实践中通常在头文件和源文件对中拆分声明和定义的方法。
foo.hpp (定义{{1}},但只声明其功能)
Foo
foo.cpp (成员函数定义)
#ifndef __FOO__
#define __FOO__
class Foo
{
int foo, bar;
public:
Foo();
Foo(int arg1, int arg2);
void doSomething();
int returnSomething();
~Foo();
};
#endif
您定义每个特定函数的位置(#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.hpp
)无关紧要,只要您只定义一次函数即可。可以在foo.cpp
或foo.hpp
,中定义,但不能同时在中定义。
关于初始化列表的问题
考虑一下:如果你在构造函数的声明上放置一个初始化列表,它就变成了声明和定义。
例如,而不是定义
foo.cpp
在源文件中,我可以在标题中定义它:
Foo::Foo(int arg1, int arg2) :
foo(arg1),
bar(arg2)
{
//body
}
唯一的区别是我没有使用范围运算符class Foo
{
...
Foo(int arg1, int arg2) :
foo(arg1),
bar(arg2)
{
//body
}
...
};
。您不会将::
放在您在类定义中声明或定义的函数前面,因为编译器已将它们识别为作用于该类的范围。