I'm new to progamming in C++. I have a good background with Java but C++ is different on many things and I have a question about one of the regarding .h and .cpp files.
I have the following files for a point object with x and y position:
Point.h
#ifndef POINT_H_
#define POINT_H_
class Point{
Point();
Point(int newX, int newY);
public:
int getX();
int getY();
void setX(int newX);
void setY(int newY);
void moveBy(int moveX, int moveY);
Point reverse();
private:
int x;
int y;
};
#endif
Point.cpp
#include "Point.h"
using namespace Point;
Point::Point(int newX, int newY){
x = newX;
y = newY;
}
int Point::getX(){
return x;
}
int Point::getY(){
return y;
}
void Point::setX(int newX){
x = newX;
}
void Point::setY(int newY){
y = newY;
}
void Point::moveBy(int moveX, int moveY){
x += moveX;
y += moveY;
}
Point Point::reverse(){
return Point(y,x);
}
I was wondering if there was a way of avoinding the Point::Point part like with std::cout by using namespace.
Thank you
You aren't required to separate your declaration and definition, and these functions are incredibly trivial. So including them in the class definition may actually allow the compiler to perform numerous additional optimizations.
So you could discard the .cpp entirely and the header becomes:
#ifndef POINT_H_
#define POINT_H_
class Point
{
int x_ { 0 };
int y_ { 0 };
public:
Point() = default;
Point(int x, int y) : x_(x), y_(y) {}
int getX() const { return x_; }
int getY() const { return y_; }
void setX(int x) { x_ = x; }
void setY(int y) { y_ = y; }
void moveBy(int x, int y) { x_ += x, y_ += y; }
Point reverse() const { return Point(y_, x_); }
};
#endif
But you can't avoid the "Point::" part when defining the members outside of the class declaration.
If you want to avoid typing the "Point::" in front of the getX, getY etc., then the answer is "no", unfortunately. In C++ and the name of any class (like "Point") is not a namespace, it's a scope.
What you can only do is inlining the method, defining into the class declaration.
class Point {
public:
void a_method() {
// all the code here!
}
};
You can't avoid "the Point::Point part," unless you declare the construction inline in the class declaration. The first "Point" defines the scope of the function, and the second "Point" is the name of the constructor function.
However, you could define the constructor(s) inline, like so:
class Point
{
Point()
{
x = 0;
y = 0;
}
Point(int newX, int newY);
{
x = newX;
y = newY;
}
// ...
};
Or:
class Point
{
Point() : x(0), y(0) {}
Point(int newX, int newY) : x(newX), y(newY) {}
// ...
};
Or:
class Point
{
Point(int newX = 0, int newY = 0) : x(newX), y(newY) {}
// ...
};
Related
I am trying to make a constructor for my Input class I get this error:
Severity Code Description Project File Line Suppression State
Error (active) E0291 no default constructor exists for class "Vector2" RunGameEngine C:\Users\imman\source\repos\RunGameEngine\RunGameEngine\Run\Input.cpp 5
for some reason intelisense wants me to create a default constructor for Vector2 even though I have one for it.
Input.h:
#pragma once
#include <GLFW/glfw3.h>
#include "Vector.h"
#include "Window.h"
class Input
{
public:
Input(GLFWwindow* window);
bool isKeyPressed(float key);
Vector2 getMousePos();
private:
bool m_keys[348];
Vector2 m_mousePos;
GLFWwindow* m_window;
};
Input.cpp:
#include "Input.h"
Input::Input(GLFWwindow* window)
{
m_window = window;
}
Vector2 Input::getMousePos()
{
glfwGetCursorPos(m_window, &m_mousePos.x, &m_mousePos.y);
return m_mousePos;
}
bool Input::isKeyPressed(float key)
{
return false;
}
Vector.h:
#pragma once
struct Vector2
{
double x, y;
Vector2(double x, double y)
{
this->x = x;
this->y = y;
}
};
struct Vector3
{
double x, y, z;
Vector3(double x, double y, double z)
{
this->x = x;
this->y = y;
this->z = z;
}
};
I would do
Vector2 Input::getMousePos()
{
double Pos_x;
double Pos_y;
glfwGetCursorPos(m_window, &Pos_x, &Pos_y);
return Vector2(Pos_x, Pos_y);
}
and just skip the m_mousePos member. You don't really want to save that anyway, do you?
Class Point is working correctly, It is creating x, y point. Code:
point.h file
#ifndef POINT_H
#define POINT_H
namespace pt
{
class Point
{
int x, y;
public:
Point();
Point(int x, int y);
int getX();
int getY();
};
}
#endif // POINT_H
point.cpp file
#include "point.h"
pt::Point::Point()
{
this->x = this->y = 0;
}
pt::Point::Point(int x, int y)
{
this->x=x;
this->y=y;
}
int pt::Point::getX()
{
return this->x;
}
int pt::Point::getY()
{
return this->y;
}
Meanwhile when I try to create new Point3D class in main that will inherit from Point x, y coordinates and add z to create third dimension, new constructor cant get access to x, y of Point class. Errors are:
1. 'int pt::Point::x' is private at first and second this-> in Point3D constr.
2. Both are 'out of context'
main.cpp
#include <iostream>
#include "point.h"
int main()
{
class Point3D : public pt::Point
{
int z;
public:
getZ()
{
return this->z;
}
Point3D(int x ,int y, int z)
{
this->x=x;
this->y=y;
this->z=z;
}
};
return 0;
}
Thanks for help.
To make x and y accessible to derived classes, you should make them protected:
class Point
{
protected:
int x, y;
public:
Point();
Point(int x, int y);
int getX();
int getY();
};
By default, the visibility of a class member is private (note that this is different from the struct default where a struct member is public by default). On that topic, see this answer.
And as a side note, the idiomatic way to initialize x and y would be to write:
Point3D(int x ,int y, int z) : pt::Point(x,y)
{
this->z=z;
}
Then, you don't need to make x and y protected, they can remain private.
You can even write it like that:
Point3D(int x ,int y, int z) : pt::Point(x,y), z(z)
{}
I am currently rewriting C code into C++ code. While doing that I am replacing structs with classes. That means that some of the variables go from public to private. Now during the transition phase I want to do some error checking by compiling the program sometimes and running it. Thus I intended to have public and private variables at the same time, which are linked, i.e. when I write something into the private variable, the public variable also changes. Nevertheless I only want to write to the private variables by using separate functions, i.e. having the public variables as read-only variables. My current approach is:
#include <iostream>
#include <stdio.h>
class test_vec
{
private:
int x, y;
int data[2];
public:
int x_ext, y_ext;
int data_ext[2];
test_vec(int x, int y)
{
this->x = x;
this->y = y;
this->x_ext = this->x;
this->y_ext = this->y;
}
~test_vec()
{}
void set_x(int x)
{
this->x = x;
}
void set_y(int y)
{
this->y = y;
}
};
int main(void)
{
std::cout << "Hello World\n";
test_vec test(1, 2);
printf("test has the properties (%d, %d)\n", test.x_ext, test.y_ext);//So far, so good
test.set_x(4);
test.set_y(10);
printf("test has the properties (%d, %d)\n", test.x_ext, test.y_ext);//Not updated!
return 0;
}
How can I change the links between the variables? At the moment I already have two pointers copied into each other, but how can I "lock" the external variable onto the internal variable?
Not sure if it's a good design pattern since inline getters are fast but you could create constant references to your private variables:
class test_vec
{
private:
int x, y;
int data[2];
public:
const int &x_ext, &y_ext;
int data_ext[2];
// you have to initialize the references before constructor body
// references cannot be let uninitialized
test_vec(int x, int y) : x_ext(this->x), y_ext(this->y)
{
this->x = x;
this->y = y;
}
~test_vec()
{}
inline void set_x(int x)
{
this->x = x;
}
inline void set_y(int y)
{
this->y = y;
}
};
when x or y changes x_ext and y_ext follow:
Hello World
test has the properties (1, 2)
test has the properties (4, 10)
Bonus: constant references cannot be modified. That's the closest thing of a read property that you got here :)
If you don't want that restriction, just remove the const qualifier, but since you're encouraging encapsuation now that you have C++ I would let it as is and let the writers hit the wall on that (not to mention a good sed/regex replacement could refactor all your writes automatically)
You can use references for these purposes.
Say you have this setup:
class myclass{
public:
myclass(int pa, float pb);
int get_a() const {return a;}
float get_b() const {return b;}
void set_a(int v) {a=v;}
void set_b(float v) {b=v;}
private:
//These are the real values, private
int a;
float b;
public:
//These are the references, public
int& ref_to_a;
float& ref_to_b;
}
myclass::myclass(int pa, float pb)
:a(pa), b(pb), ref_to_a(a), ref_to_b(b)
{
}
You can go like this:
myclass c(33, 12.3f);
c.set_a(12);
c.set_b(111.1f);
//This...
std::cout<<c.ref_to_a<<" "<<c.ref_to_b<<std::endl;
//Should be the same as this...
std::cout<<c.get_a()<<" "<<c.get_b()<<std::endl;
Notice the access settings: the references are public, meaning you can write and read from them. If you want them to be read only you can play with the constness.
I wouldn't bother. Just make the members public for the moment, and when you have fixed all the external references, make them private.
class test_vec
{
public: // For now. Will become private later
int x, y;
public: // For now.
int data[2];
public: // For ever
test_vec(int x, int y)
: x(x), y(y) // Prefer initialization to assignment.
{
}
~test_vec()
{}
void set_x(int x)
{
this->x = x;
}
void set_y(int y)
{
this->y = y;
}
int get_x() const { return x; } // etc
};
If you really wanted to, you could make x_ext be a reference to const - but it's much more idiomatic in C++ to make getters be functions.
class test_vec
{
private:
int x, y;
int data[2];
public:
int const& x_ext;
int const& y_ext;
test_vec(int x_, int y_)
: x(x_), y(y_)
, x_ext(x), y_ext(y) // You *have* to use initialization here.
{
}
~test_vec()
{}
void set_x(int x)
{
this->x = x;
}
void set_y(int y)
{
this->y = y;
}
};
I have a class, along with it's objects. What do I do if I want each object to do something different? (AKA each object has a unique function).
Here is a simplified code of what I am trying to achieve.
The basic class
class Thing
{
private:
int x, y, z;
public:
static vector<Thing*> objects;
int getX() {return x;}
int getY() {return y;}
int getZ() {return z;}
Thing(int X, int Y, int Z)
{
this->x = X;
this->y = Y;
this->z = Z;
objects.push_back(this);
}
void func(); //THE EVENTUAL UNIQUE FUNCTION
};
vector<Thing*> Thing::objects = {};
My theoretical desired code
int main()
{
Thing A(1, 2, 3);
void A->func() //A REDEFINITION OF THE PUBLIC FUNCTION
{
cout << "do stuff" << endl;
}
}
Use std::function and C++11 lambdas
class Thing
{
private:
int x, y, z;
public:
static vector<Thing*> objects;
int getX() {return x;}
int getY() {return y;}
int getZ() {return z;}
Thing(int X, int Y, int Z)
{
this->x = X;
this->y = Y;
this->z = Z;
objects.push_back(this);
}
std::function<void()> func; //THE EVENTUAL UNIQUE FUNCTION
};
Redefine unique function
A.func = [&A]() {
// do something
};
Can anybody help me with the syntax of passing an array of classes
to another class. The syntax of passing an array of classes to another
class has got me beaten. class line tries to be initialised by an
array of points, but the prototype does not match.
#include <iostream>
using namespace std;
class point {
public:
point() {}
point(int x, int y) : X(x), Y(y) {}
void setXY(int x, int y) { X = x; Y = y; }
int getX() { return X; }
int getY() { return Y; }
private:
int X, Y;
};
class line {
public:
line(point *points, int); // Problem line.
private:
point *coords;
int numpoints;
};
int main() {
point points[3];
points[0].setXY(3, 5);
points[1].setXY(7, 9);
points[2].setXY(1, 6);
line l(points, 3); // Problem line.
return 0;
}
Error message:
cygdrive/c/Tmp/cc4mAXRG.o:a.cpp:(.text+0xa7): undefined reference to `line::line(point*, int)'
You need to define a constructor for your line class - you've only provided a declaration.
#include <iostream>
using namespace std;
class point {
public:
point() {}
point(int x, int y) : X(x), Y(y) {}
void setXY(int x, int y) { X = x; Y = y; }
int getX() { return X; }
int getY() { return Y; }
private:
int X, Y;
};
class line {
public:
line(point *points, int count)
: coords(points), numpoints(count) {}
private:
point *coords;
int numpoints;
};
int main() {
point points[3];
points[0].setXY(3, 5);
points[1].setXY(7, 9);
points[2].setXY(1, 6);
line l(points, 3);
return 0;
}
I'd recommend taking a look at the difference between definitions and declarations. Additionally, you should consider maintaining a std::vector<point> in your line class to manage the points. Your line class might then behave as:
#include <vector>
class line {
public:
line(std::vector<point> points)
: coords(points), numpoints(coords.size()) {}
private:
std::vector<point> coords;
int numpoints;
};
You didn't provide a definition for the constructor.
Try:
line(point *points, int np) : coords(points), numpoints(np) {}
Missing body of constructor "line".
You define prototype only.