0

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;
};
4
  • 2
    You only need to set the default values for a function's parameters once, when it's declared. In any case, I note that you wrote Stone::Stone but you didn't write Stone::SetPos or similar. Also, did you #include your header file anywhere in the cpp file? Commented Jan 5, 2021 at 20:19
  • More to the former point, you see how you resolved the Stone constructor by prefacing it with the qualifying Stone:: ? Yeah, you need to do that for every member you likewise implemented out of the class namespace. Commented Jan 5, 2021 at 20:25
  • Thanks for your comment, I will try to adjust my code. I did #include my header file in the .cpp and in a main.cpp Commented Jan 5, 2021 at 20:29
  • @NathanPierson So I edited my code so that every method has Stone::. The only thing I'm still confused about is the constructor. This is what I tried in the header file, so the default values are not declared: Stone(double x, double y); Commented Jan 5, 2021 at 20:43

2 Answers 2

1

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
}
Sign up to request clarification or add additional context in comments.

Comments

0

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"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.