开发者

C++ What to put in a Class Declaration and what not

开发者 https://www.devze.com 2023-02-14 17:28 出处:网络
I\'m totally confused where to put e.g. the definition of a constructor. Sometimes you see something like this

I'm totally confused where to put e.g. the definition of a constructor. Sometimes you see something like this

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

Then you sometimes see someth开发者_如何学Pythoning like this:

// 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;
}

I.e. sometimes things like constructors, copy constructors etc. get declared in the .h and then implemented in the .cc file, sometimes they get defined in the header and so on. But under which circumstances? Which is good practice, which is not?


Contrary to some of the answers there are differences in these two practices.

If you put the implementation into the class declaration the method will be automatically marked as inline. For very short methods like wrappers this is a advisable practice very useful feature.

If you put the implementation into a separate .cc file you're increasing the readability (as David Titarenco already wrote in his answer) and decreasing possible dependencies in your project. Classes which only occur as references, pointers or return values in the method declaration only need a forward declaration in the header. Their implementation details are irrelevant here and thus for every file including this header too. An example:

// 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.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() { /*...*/ }
// ...

Now if you include test.h into another .cc file and the declaration of class A changed, only test.cc need to be recompiled and not the other .cc file. The declaration of the class B didn't change.

Besides that: There are situations where you're obliged to put the implementations in your header: If you're writing class or function templates or really want a function being declared as inline.

As Omnifarious exactly commented: The attached code you sometimes saw will be surely refused by every C++ compiler. const members of a class must be initialized in an initializer-list. Afterwards they stay fixed and no default assignment operator will be provided for you. This means even if you're using a initializer-list, you'll never be able to write something like that as long as you didn't overload the assignment operator:

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

If you really need constant coordinates you should write const Point p(10, 20).


It's usually better to keep declarations in the header and implementations in the source. With that said, it's completely up to the author(s).

As long as it's readable :)


If using header files, it's usually good practice to only define the methods in the header, and implement them in the cpp.

You can have class methods (and constructors/destructors) defined inside or outside the class definition. There is no problem with neither, it's just a matter of style.

The diference is just in syntax, because if you define a method outside of a class, you have to add TheClassName:: just before the name of the method (but after the type).


You should keep all function implementations outside the header file, unless

  • You have to because they are templates
  • You want them to be inlined, and your compiler doesn't do LTCG.

A clean header file is invaluable to get a quick overview of what a class does and how you're supposed to use it.


Of course, both of those definitions are not the best way. Though that's only peripherally relevant to your question.

The answer is, that you should use the first style of definition if the method is very short and doesn't clutter up the class definition. The first style, inside the class, has the effect of putting an implicit inline keyword in front of the definition.

The second style can also be declared in a header file, and you can use an explicit inline keyword. This is more common if the method is more complex, or if it's part of a template specification where the full definition needs to be available so the template can be instantiated properly with current compilers.

So, mostly it's a matter of style which sort of definition you use. Though if you use the second style, the external to the class declaration style, and your method is declared in a header file, your method should be declared explicitly inline or be a member of a template class. Otherwise the linker may end up giving you duplicate definition warnings.

Lastly, here is how the method should really be defined:

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

This is because the members are const. They must be initialized within the constructors initializer list, not within the constructor body. In the constructor body those assignments are illegal because the members are const.

It is a good habit to always use initializer lists to initialize members anyway though, regardless of whether or not they are const. This is because if you use assignment in the constructor body you end up calling the default constructor for the member, and then assigning something to it. This is likely more expensive than simply initializing it with the proper value in the first place, especially if the type isn't a primitive type.

It also helps prevent errors because your members are always initialized instead of having their initialization depend on the control flow within the constructor body.

0

精彩评论

暂无评论...
验证码 换一张
取 消