将此类分为头文件和 cpp 文件

时间:2021-01-05 20:16:04

标签: c++

我很难将这个类分成头文件和 .cpp 文件,因为 C++ 对我来说相对较新。这门课是我的老师在课堂上给我们编程的一个例子。这不是家庭作业,但它会帮助我理解我的家庭作业。

#include <iostream>
#include <AstUtils.h>
#include <vector>
#include <cassert>
#include <Vector2.h>

#define WIDTH 1377
#define HEIGHT 768

using namespace std;
using namespace astu;

class Stone {
public:

Stone(double x = 0, double y = 0)
    : x(x), y(y), vx(0), vy(0)
{
//empty
}
void SetPos(double x, double y){
    this->x = x;
    this->y = y;
}

void Render() {
    SetRenderColor(255,0,0);
    RenderRectangle(x,y,20,20,true);
}

double GetPosX() const {
    return x;
}

double GetPosY() const {
    return y;
}

void SetVel(double vx, double vy){
    this->vx = vx;
    this->vy = vy;
}

void SetAcc(double ax, double ay){
    this->ax = ax;
    this->ay = ay;
}

void Update(double dt) {
    x += vx*dt;
    y += vy*dt;

    vx += ax*dt;
    vy += ay*dt;

    ax = 0;
    ay = 0;
}

private:
    double x,y;
    double vx, vy;
    double ax, ay;
};


void PlotCurve(vector<double> & vertices) {
assert(vertices.size() % 2 == 0);
assert(vertices.size() >= 4);

auto it = vertices.begin();

double x1 = *it++;
double y1 = *it++;

while(it != vertices.end()){
double x2 = *it++;
double y2 = *it++;
RenderLine(x1,y1, x2, y2);
x1 = x2;
y1 = y2;
}
}

void ReportError()
{
std::cout << "An error has occured: " << GetLastErrorMessage() << std::endl;
std::cout << GetErrorDetails() << std::endl;
}

int main()
{
if (InitApp(WIDTH,HEIGHT, "Demo") != NO_ERROR) {
ReportError();
return -1;
}

Vector2<double> center(WIDTH/2, HEIGHT/2);

Stone stone(WIDTH * 0.3, HEIGHT/2);
stone.SetVel(100, -150);

vector<double> posCurve;
posCurve.push_back(stone.GetPosX());
posCurve.push_back(stone.GetPosY());

while(!IsAppTerminated()) {
    ClearCanvas();

    Vector2 p(stone.GetPosX(), stone.GetPosY());
    Vector2 d = center - p;
    double dist = d.LengthSquared();

    d.Normalize();
    d *= 50000000 / dist;

    stone.SetAcc(d.x,d.y);

    stone.Update(GetDeltaTime());
    stone.Render();

    posCurve.push_back(stone.GetPosX());
    posCurve.push_back(stone.GetPosY());
    SetRenderColor(255,255,255);
   PlotCurve(posCurve);

    UpdateApp();
}

QuitApp();

}

这是我试过的:

(不知道如何定义构造函数,也有问题,因为变量在标题中。)

.cpp:

Stone::Stone(double x = 0, double y = 0)
    : x(x), y(y), vx(0), vy(0)
{}

void SetPos(double x, double y){
    this->x = x;
    this->y = y;
}

void Render() {
    SetRenderColor(255,0,0);
    RenderRectangle(x,y,20,20,true);
}

double GetPosX() const {
    return x;
}

double GetPosY() const {
    return y;
}

void SetVel(double vx, double vy){
    this->vx = vx;
    this->vy = vy;
}

void SetAcc(double ax, double ay){
    this->ax = ax;
    this->ay = ay;
}

void Update(double dt) {
    x += vx*dt;
    y += vy*dt;

    vx += ax*dt;
    vy += ay*dt;

    ax = 0;
    ay = 0;
}

.h:

class Stone{
public:

    Stone(double x = 0, double y = 0);

    void SetPos(double x, double y);

    void Render();

    double GetPosX();

    double GetPosY();

    void SetVel(double vx, double vy);

    void SetAcc(double ax, double ay);

    void Update(double dt);

private:

    double x,y;
    double vx, vy;
    double ax, ay;
};

2 个答案:

答案 0 :(得分:1)

您不一定需要将所有实现移动到 .cpp 文件中。当它足够短并且不使用类外部的任何对象时,您可以将实现作为内联函数保留在 .hpp 文件中。对于 getPosXgetPosY 等成员尤其如此。内联这样的成员会增加空间,但也可能会导致代码速度更快。

我通常保留可以在一行中编写的类声明函数,如下所示:

double GetPosX() const { return x; }
double GetPosY() const { return y; }

但是,如果函数需要包含另一个标头,我会将实现移到 .cpp 文件中以尽可能避免包含在标头中:

double GetPosX() const;
double GetPosY() const;

.cpp中:

#include AnotherClass.hpp

double Stone::GetPosX() const {  return anotherClass.x; }
double Stone::GetPosY() const {  return anotherClass.y; }

对于构造函数,您可以将其保留在标题中,尤其是在它为空的情况下,如您的示例所示:

Stone(double x = 0, double y = 0) : x(x), y(y), vx(0), vy(0)
{}

但是,如果它是一个更复杂的实现,你也应该移动它:

// In the header
Stone(double x = 0, double y = 0);
// In the cpp
Stone::Stone(double x, double y) : x(x), y(y), vx(0), vy(0) 
{
    //Complex implementation of the constructor
}

答案 1 :(得分:0)

你需要在cpp中声明你定义的函数的作用域。

标题:

// use a "guard" to avoid duplicate includes in compilation units
#pragma once
// if compiler doesn't support "#pragma once" do
/*
#ifndef _classname_
#define _classname_
*/

class C {
  private:
    int a;
    static const int B;
  public:
    C(int); // ctor
    void setA(const int&);
    int getA() const;
};

/*
#endif
*/

Cpp:

#include <header.h>

// constants need to be defined in the compilation unit,
// because the header might be included (read: copy & pasted)
// in multiple different compilation units and suddenly
// you have a class with multiple constants
static const int C::b = 4;

// constructor with member initializer list
C::C(int a) : a(a)
{
  // empty
}

// normal function
void C::setA(const int& a) {
  this->a = a;
}

// const function
int C::getA() const {
  return a;
}

并且请不要在头文件中使用 using namespace,因为这可能会弄乱包含它们的任何人的代码。 请记住 #include <file> 是“在此处复制文件内容”

相关问题