简体   繁体   中英

Seperating this class into a header and cpp file

I have difficulties with separating this class into a header and.cpp file because c++ is relatively new for me. This class is an example my teacher programmed with us in class. It isn't homework, but it will help me understand my homework.

#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();

}

This is what I tried:

(Didn't know how to define the constructor and also had problems with this, since the variables are in the header.)

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

You don't necessarily need to move all implementations into the .cpp file. When it is sufficiently short and doesn't make use of any object external to the class, you could keep the implementation in the .hpp file as an inline function. This is especially true for members like getPosX or getPosY . Inlining a member like that is a gain of space but could also result in faster code.

I generally keep in the class declaration functions that I can write on a single line, like this:

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

However, if the function requires the inclusion of another header, I move the implementation to the .cpp file to avoid inclusions in the header as much as possible:

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

In .cpp :

#include AnotherClass.hpp

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

For the constructor, you can keep it in the header, especially if it is empty, as in your example:

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

But, if it would be a more complex implementation, you should move it, too:

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

You need to declare the scope of the functions you define in the cpp.

Header:

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

And please do not use using namespace in header files, as that might mess up the code of anyone who includes them. Remember #include <file> is "copy file contents here"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM