我对如何将一个简单类的实现和声明代码分离到一个新的头文件和cpp文件感到困惑。例如,我如何为下面的类分离代码?

class A2DD
{
  private:
  int gx;
  int gy;

  public:
  A2DD(int x,int y)
  {
    gx = x;
    gy = y;
  }

  int getSum()
  {
    return gx + gy;
  }
};

基本上是函数声明/定义的修改语法:

a2dd.h

class A2DD
{
private:
  int gx;
  int gy;

public:
  A2DD(int x,int y);

  int getSum();
};

a2dd.cpp

A2DD::A2DD(int x,int y)
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

在头文件中保留声明:

class A2DD
{
  private:
  int gx;
  int gy;

  public:
    A2DD(int x,int y); // leave the declarations here
    int getSum();
};

并将定义放在实现文件中。

A2DD::A2DD(int x,int y) // prefix the definitions with the class name
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

您可以混合使用这两种方法(例如将getSum()定义保留在头文件中)。这很有用,因为它为编译器提供了更好的内联机会。但这也意味着改变实现(如果留在头文件中)可能会触发包含头文件的所有其他文件的重新构建。

注意,对于模板,您需要将所有内容都保存在头文件中。


A2DD.h

class A2DD
{
  private:
  int gx;
  int gy;

  public:
  A2DD(int x,int y);

  int getSum();
};

A2DD.cpp

  A2DD::A2DD(int x,int y)
  {
    gx = x;
    gy = y;
  }

  int A2DD::getSum()
  {
    return gx + gy;
  }

其思想是将所有函数签名和成员保存在头文件中。 这将允许其他项目文件看到类的样子,而不需要知道实现。

除此之外,你还可以在实现中包含其他头文件,而不是头文件。这一点很重要,因为头文件中包含的任何头文件都将包含(继承)在包含您的头文件的任何其他文件中。


类声明放在头文件中。添加#ifndef include守卫是很重要的。大多数编译器现在也支持#pragma一次。另外,我省略了private,默认情况下c++类成员是private。

// A2DD.h
#ifndef A2DD_H
#define A2DD_H

class A2DD
{
  int gx;
  int gy;

public:
  A2DD(int x,int y);
  int getSum();

};

#endif

实现在CPP文件中:

// A2DD.cpp
#include "A2DD.h"

A2DD::A2DD(int x,int y)
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

 

通常你只在头文件中放入声明和非常短的内联函数:

例如:

class A {
 public:
  A(); // only declaration in the .h unless only a short initialization list is used.

  inline int GetA() const {
    return a_;
  }

  void DoSomethingCoplex(); // only declaration
  private:
   int a_;
 };

通常你的.h包含类定义,它是你所有的数据和所有的方法声明。你的情况是这样的:

A2DD.h:

class A2DD
{
  private:
  int gx;
  int gy;

  public:
  A2DD(int x,int y);    
  int getSum();
};

然后你的.cpp包含了这些方法的实现,就像这样:

A2DD.cpp:

A2DD::A2DD(int x,int y)
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

重要的是要向读者指出,当你在更广泛的方式下研究这个主题时,偶然遇到这个问题,如果你只是想把你的项目分割成文件,那么接受答案的过程是不需要的。只有当您需要单个类的多个实现时才需要它。如果每个类的实现是一个,那么每个类只需要一个头文件就足够了。

因此,从被接受的答案的例子中,只需要这一部分:

#ifndef MYHEADER_H
#define MYHEADER_H

//Class goes here, full declaration AND implementation

#endif

#ifndef等预处理器定义允许它被多次使用。

PS:一旦你意识到C/ c++是“愚蠢的”,#include仅仅是一种表示“在此处转储文本”的方式,这个主题就会变得更加清晰。


我不会参考你的例子,因为它很简单(例如,它不包含模板化函数,这迫使你在头文件上实现它们),我遵循的经验法则是pimpl习语

它有很多好处,因为你可以得到更快的编译时间和语法糖:

Class ->成员而不是Class .member

唯一的缺点是你要支付额外的指针。