C++什么可以放入类声明中,什么不可以

hel*_*hod 3 c++

我完全混淆在哪里放置例如构造函数的定义.有时你会看到类似的东西

// point.h
class Point {
  Point(int x, int y) {
    x_ = x;
    y_ = y;
  }
private:
  const int x_;
  const int y_;
}
Run Code Online (Sandbox Code Playgroud)

然后你有时会看到这样的事情:

// point.h
class Point {
  Point(int x, int y);
private:
  const int x_;
  const int y_;
}

// point.cc
Point::Point(int x, int y) {
  x_ = x;
  y_ = y;
}
Run Code Online (Sandbox Code Playgroud)

即有时像构造函数,复制构造函数等.h.cc文件中声明然后在文件中实现,有时它们在头文件中定义,依此类推.但在哪种情况下呢?哪个是好习惯,哪个不是?

phl*_*psy 5

与一些答案相反,这两种做法存在差异.

如果将实现放入类声明中,该方法将自动标记为inline.对于像包装这样的非常短的方法,这是一个可行的做法 非常有用的功能.

如果您将实现放入单独的.cc文件中,那么您可以提高可读性(正如David Titarenco已经在他的回答中所写)并减少了项目中可能的依赖性.仅在方法声明中作为引用,指针或返回值出现的类只需要在标头中使用前向声明.它们的实现细节在这里无关紧要,因此对于包含此标题的每个文件也是如此.一个例子:

// test.h
class A; // forward declaration of A
// #include "decl_of_class_A.h" // not needed here, because ...

class B {
public:
  A method1();        // in these cases the forward
  void method2(A* a); // declaration of A above 
  void method3(A& a); // is completely sufficient.
};
Run Code Online (Sandbox Code Playgroud)

// test.cc
#include "decl_of_class_A.h" // here we really need
                             // the complete declaration of A
                             // in order to be able to *use* it

A B::method1() { /*...*/ }
// ...
Run Code Online (Sandbox Code Playgroud)

现在,如果您包含test.h到另一个.cc文件并且类的声明已A更改,则只test.cc需要重新编译而不是其他.cc文件.班级宣言B没有改变.

除此之外:有些情况下你必须将实现放在标题中:如果你正在编写类或函数模板或者真的想要一个函数被声明为inline.

正如Omnifarious所评论的那样:您有时看到的附加代码肯定会被每个C++编译器拒绝.const必须在初始化列表中初始化类的成员.之后它们会保持固定状态,并且不会为您提供默认的赋值运算符.这意味着即使您使用的是初始化列表,只要您没有重载赋值运算符,您就永远无法编写类似的东西:

Point p(10, 20);
Point q(0, 0);
q = p; // no assignment operator provided ==> error!
Run Code Online (Sandbox Code Playgroud)

如果你真的需要恒定坐标,你应该写const Point p(10, 20).