将类代码分隔为标头和cpp文件

drd*_*rdr 154 c++ oop class

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

class A2DD
{
  private:
  int gx;
  int gy;

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

  int getSum()
  {
    return gx + gy;
  }
};
Run Code Online (Sandbox Code Playgroud)

Fer*_*eak 214

类声明进入头文件.添加#ifndef包含警卫很重要,或者如果您在MS平台上也可以使用#pragma once.另外我省略了私有,默认情况下C++类成员是私有的.

// A2DD.h
#ifndef A2DD_H
#define A2DD_H

class A2DD
{
  int gx;
  int gy;

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

};

#endif
Run Code Online (Sandbox Code Playgroud)

并且实现在CPP文件中:

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

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

int A2DD::getSum()
{
  return gx + gy;
}
Run Code Online (Sandbox Code Playgroud)

  • 请记住,如果您正在进行模板编程,那么您必须将所有内容保存在.h文件中,以便编译器在编译时实例化正确的代码. (43认同)
  • 所以这意味着包含头文件的所有文件都将"看到"私有成员.例如,如果要发布lib及其标题,则必须显示该类的私有成员? (3认同)
  • 您的标头中有#ifndef吗? (2认同)
  • 不,有一个美妙的私有实现习惯用法:http://en.wikipedia.org/wiki/Opaque_pointer 您可以使用它来隐藏实现细节。 (2认同)
  • 小nitpick的写法是:“类声明进入头文件”。这确实是一个声明,但它也是一个定义,但是由于后者包括前者,我宁愿说类定义进入了头文件。在翻译单元中,您具有成员函数的定义,而不是类的定义。我同意,这可能值得小修改吗? (2认同)

小智 16

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

A2DD.h:

class A2DD
{
  private:
  int gx;
  int gy;

  public:
  A2DD(int x,int y);    
  int getSum();
};
Run Code Online (Sandbox Code Playgroud)

然后你的.cpp包含这样的方法的实现:

A2DD.cpp:

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

int A2DD::getSum()
{
  return gx + gy;
}
Run Code Online (Sandbox Code Playgroud)


j r*_*riv 11

在以更广泛的方式研究该主题时,向遇到此问题的读者指出这一点很重要,如果您只想将项目拆分为文件,则不需要接受的答案的过程。仅当您需要单个类的多个实现时才需要它。如果每个类的实现是一个,那么每个类只需要一个头文件就足够了。

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

#ifndef MYHEADER_H
#define MYHEADER_H

//Class goes here, full declaration AND implementation

#endif
Run Code Online (Sandbox Code Playgroud)

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

附注。一旦您意识到 C/C++ 是“愚蠢的”并且#include 只是一种说“在此位置转储此文本”的方式,主题就会变得更加清晰。

  • 我认为某些项目将头文件和(单个)实现文件分开,以便他们可以轻松分发头文件,而无需透露实现的源代码。 (2认同)
  • “多个实现”之一可能是用于单元测试的模拟。 (2认同)

Cor*_*bin 5

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

a2dd.h

class A2DD
{
private:
  int gx;
  int gy;

public:
  A2DD(int x,int y);

  int getSum();
};
Run Code Online (Sandbox Code Playgroud)

a2dd.cpp

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

int A2DD::getSum()
{
  return gx + gy;
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*Mat 5

您将声明留在头文件中:

class A2DD
{
  private:
  int gx;
  int gy;

  public:
    A2DD(int x,int y); // leave the declarations here
    int getSum();
};
Run Code Online (Sandbox Code Playgroud)

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

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

int A2DD::getSum()
{
  return gx + gy;
}
Run Code Online (Sandbox Code Playgroud)

你可以混合两者(离开getSum()例如将定义保留在标题中)。这很有用,因为它使编译器有更好的机会进行内联等。但这也意味着更改实现(如果保留在标头中)可能会触发包含标头的所有其他文件的重建。

请注意,对于模板,您需要将其全部保留在标题中。


Yoc*_*mer 5

A2DD.h

class A2DD
{
  private:
  int gx;
  int gy;

  public:
  A2DD(int x,int y);

  int getSum();
};
Run Code Online (Sandbox Code Playgroud)

A2DD.cpp

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

  int A2DD::getSum()
  {
    return gx + gy;
  }
Run Code Online (Sandbox Code Playgroud)

这个想法是在头文件中保留所有函数签名和成员。
这将允许其他项目文件查看类的外观,而无需知道实现。

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