Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;在类声明中放什么,不放什么_C++ - Fatal编程技术网

C++ C++;在类声明中放什么,不放什么

C++ C++;在类声明中放什么,不放什么,c++,C++,我完全不知道该把构造器的定义放在哪里。有时你会看到这样的事情 // point.h class Point { Point(int x, int y) { x_ = x; y_ = y; } private: const int x_; const int y_; } 然后你有时会看到这样的情况: // point.h class Point { Point(int x, int y); private: const int x_; const in

我完全不知道该把构造器的定义放在哪里。有时你会看到这样的事情

// point.h
class Point {
  Point(int x, int y) {
    x_ = x;
    y_ = y;
  }
private:
  const int x_;
  const int y_;
}
然后你有时会看到这样的情况:

// 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;
}
例如,有时构造函数、复制构造函数等在
.h
中声明,然后在
.cc
文件中实现,有时在标题中定义,等等。
但是在什么情况下呢?哪一个是好的实践,哪一个不是

如果使用头文件,通常最好只在头文件中定义方法,并在cpp中实现它们

可以在类定义内部或外部定义类方法(以及构造函数/析构函数)。两者都没有问题,只是风格问题


区别在于语法,因为如果在类之外定义方法,则必须在方法名称之前(但在类型之后)添加
类名::

通常最好将声明保留在头中,将实现保留在源中。话虽如此,这完全取决于作者


只要可读:)

您应该将所有函数实现都保留在头文件之外,除非

  • 您必须这样做,因为它们是模板
  • 您希望它们是内联的,而您的编译器不执行LTCG

一个干净的头文件对于快速了解一个类的功能以及您应该如何使用它是非常宝贵的。

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

如果将实现放入类声明中,该方法将自动标记为
inline
。对于像wrappers这样的非常短的方法,这是一个非常有用的特性

如果将实现放在一个单独的
.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.
};

现在,如果您将
test.h
包含到另一个
.cc
文件中,并且类
A
的声明已更改,则只需重新编译
test.cc
,而无需重新编译另一个
.cc
文件。类
B
的声明没有更改

除此之外:在某些情况下,您必须将实现放在标题中:如果您正在编写类或函数模板,或者确实希望函数声明为
内联

作为全称的注释:你有时看到的附加代码肯定会被每个C++编译器拒绝。代码>常量类的成员必须在初始值设定项列表中初始化。之后,它们将保持不变,并且不会为您提供默认的赋值运算符。这意味着,即使您使用的是初始值设定项列表,您也永远无法编写类似的内容,只要您没有重载赋值运算符:

Point p(10, 20);
Point q(0, 0);
q = p; // no assignment operator provided ==> error!

如果你真的需要常量坐标,你应该写
常量点p(10,20)

当然,这两种定义都不是最好的方法。虽然这只是与你的问题无关

答案是,如果方法很短并且不会使类定义混乱,那么应该使用第一种定义样式。类内部的第一种样式的效果是在定义前面放置一个隐式
inline
关键字

第二种样式也可以在头文件中声明,并且可以使用显式
inline
关键字。如果方法更复杂,或者如果它是模板规范的一部分,需要提供完整的定义,以便使用当前编译器正确实例化模板,则这种情况更常见

所以,主要是风格的问题,你使用哪种定义。虽然如果您使用第二种样式,即类声明样式的外部样式,并且您的方法在头文件中声明,那么您的方法应该显式内联声明,或者是模板类的成员。否则,链接器最终可能会给您重复的定义警告

最后,这里是如何真正定义方法:

class Point {
  Point(int x, int y) : x_(x), y_(y) { }
private:
  const int x_;
  const int y_;
};
这是因为成员是
const
。它们必须在构造函数初始值设定项列表中初始化,而不是在构造函数体中初始化。在构造函数主体中,这些赋值是非法的,因为成员是
const

无论如何,始终使用初始值设定项列表初始化成员是一个好习惯,不管它们是否为
const
。这是因为如果在构造函数体中使用赋值,则最终会调用成员的默认构造函数,然后为其赋值。这可能比一开始就用适当的值初始化要昂贵,尤其是当类型不是基元类型时


它还有助于防止错误,因为您的成员总是初始化的,而不是让它们的初始化依赖于构造函数体中的控制流。

区别不仅仅在于语法;类定义中定义的成员函数是自动
内联的
,这意味着它的定义可以在多个编译单元中重复。-1:您可以说“(但在返回类型之后)”更清楚,因为
类名::
也表示类型,但更重要的是,C++中的字段和方法默认为公共的说法是错误的。在结构中,默认情况下它们是公共的;在类中,默认情况下它们是私有的。显然,使用
public:
private:
会覆盖默认值
class Point {
  Point(int x, int y) : x_(x), y_(y) { }
private:
  const int x_;
  const int y_;
};