Calling a constructor of a class, inherited by multiple classes - c++

Straight to the point:
I've got 2 classes. One stores one set of information, another - different information.
.h file
class Direction
{
private:
std::vector<float> dir;
public:
Direction(std::vector<float> objDir); ......};
.cpp file
#ifndef frw_dir_ed
#define frw_dir_ed
#include "frw_direction.h"
#endif
FRW::Direction::Direction(std::vector<float> objDir = { .0f, .0f })
{
for (int i = 0; i < 2; i++)
dir[i] = objDir[i];
}
Direction(float x, float y);
Another .h file:
class Position
{
private:
float posX;
float posY;
public:
Position(float x, float y);
Another .cpp file:
#ifndef frw_pos_ed
#define frw_pos_ed
#include "frw_position.h"
#endif // !frw_pos_ed
FRW::Position::Position(float x = 0, float y = 0)
{
setPos(x, y);
}
I also have a third class. This one inherits 2 previous.
class gameObj : public Position, public Direction
{
public:
gameObj(float x, float y, std::vector<float> direction, bool renderable);
gameObj(float posX, float posY, float dirX, float dirY, bool renderable);
//some funcs, destructor
private:
FRW::Position objPos;
FRW::Direction objDir;
bool isRendered;
};
That was a header file, now .cpp:
FRW::gameObj::gameObj(float x = 0.5f, float y = 0.5f, std::vector<float> direction = { .0f, .0f }, bool renderable = true)
: FRW::Direction::Direction(direction), FRW::Position::Position(x,y)
{
isRendered = renderable;
}
FRW::gameObj::gameObj(float posX = 0.5f, float posY = 0.5f, float dirX = .0f, float dirY = 0.f, bool renderable = true)
: FRW::Direction::Direction(dirX, dirY), FRW::Position::Position(posX, posY)
{
isRendered = renderable;
}
C2456 compiler error: member function or nested class in costructor initializer list
Error 3 error C2535: 'void FRW::gameObj::__dflt_ctor_closure(void)' : member function already defined or declared.
Please, can anyone tell me, which concept of OOP I missed? Why I am getting this error?

You either need to inherit from a class or have an element of that type as a member, not both! i.e. this:
class gameObj
{
public:
// ...
private:
FRW::Position objPos;
FRW::Direction objDir;
bool isRendered;
};
or this:
class gameObj : public Position, public Direction
{
public:
// ...
private:
bool isRendered;
};
but not this:
class gameObj : public Position, public Direction
{
public:
// ...
private:
FRW::Position objPos;
FRW::Direction objDir;
bool isRendered;
};
(Actually it's possible you'd want the last one, but very rare in practice.) With the last one, you end up with two directions in gameObj: the gameObj::objDir member, and the direction that the gameObj inherits from. In this case you probably want the member variable (a person has a direction, but it's not true that a person is a direction).This is called using composition rather than inheritance, and it's usually best if you can get away with it. As guide, you normally shouldn't use inheritance unless you need virtual functions. The reason for the compilation error is that you're only initialising one of those two directions (and one of the two positions).
By the way, the error would have been hidden by the fact that you have default values for the constructors. But they need to be in the header than the .cpp (otherwise only code in the .cpp after the definitions will "know" about the defaults).
Edit: Additionally, the code FRW::Direction::Direction(dirX, dirY) should be FRW::Direction(dirX, dirY). This is the real cause of the compilation error (but once you fix it I think you'll get the error I mention above).

Related

(SFML) Issues with inheritance (C++)

So, I'm using SFML and I'm trying to setup an entity class and a player sub-class that inherits from it, but this is my first time working with inheritance and I'm having issues:
First, I have an AssetManager class that I cobbled together from different sources, since I don't quite understand how they work yet:
AssetManager.h:
class AssetManager {
public:
AssetManager();
static sf::Texture& LoadTexture(std::string const& path);
static sf::SoundBuffer& LoadSoundBuffer(std::string const& path);
static sf::Font& LoadFont(std::string const& path);
private:
std::map<std::string, sf::Texture> m_Textures;
std::map<std::string, sf::SoundBuffer> m_SoundBuffers;
std::map<std::string, sf::Font> m_Fonts;
static AssetManager* sInstance;
};
But you can only need to see the part relating to textures, here is that part from AssetManager.cpp:
AssetManager* AssetManager::sInstance = nullptr;
AssetManager::AssetManager() {
assert(sInstance == nullptr);
sInstance = this;
}
sf::Texture& AssetManager::LoadTexture(std::string const& path) {
auto& texMap = sInstance->m_Textures;
auto pairFound = texMap.find(path);
if (pairFound != texMap.end()) {
return pairFound->second;
}
else {
auto& texture = texMap[path];
texture.loadFromFile(path);
return texture;
}
}
Then an object of that class is included inside a Sprite class, that facilitates declaring sprites for me.
Sprite.h:
class Sprite {
public:
AssetManager manager;
sf::Texture m_Texture;
sf::Sprite m_Sprite;
sf::Vector2f sprite_scale;
sf::Vector2u original_size;
sf::Vector2f texture_size;
Sprite(std::string path,sf::IntRect rect,sf::Vector2f size);
};
Sprite.cpp:
Sprite::Sprite(std::string path, sf::IntRect rect, sf::Vector2f size) {
m_Texture = sf::Texture(AssetManager::LoadTexture(path));
m_Sprite.setTextureRect(rect);
m_Sprite.setTexture(m_Texture);
original_size = m_Texture.getSize();
texture_size.x = static_cast<float>(original_size.x);
texture_size.y = static_cast<float>(original_size.y);
sprite_scale.x = size.x / texture_size.x;
sprite_scale.y = size.y / texture_size.y;
m_Sprite.setScale(sf::Vector2f(sprite_scale.x, sprite_scale.y));
m_Sprite.setOrigin(sf::Vector2f(original_size.x / 2, original_size.y / 2));
}
Then, an object of the Sprite class is itself included within an Entity class.
Entity.h:
class Entity {
public:
Sprite entity_sprite;
int health;
float speed;
bool collision = false;
bool entity_collision(sf::Sprite entity2_sprite);// Entity.cpp only contains the declaration of this function so far so no need to post it.
};
Now, for a reason I don't understand, I'm not able to directly assign any arguments to the entity_sprite object when declaring it, and I'm only able to declare it with no arguments, despite the class having not a default constructor.
However I am able to get around it using assignment:
Entity entity_sprite = Entity("res/wildcard.png", { 0,0,36,63 }, { 36,63 });
But this isn't the main issue, and using the Entity class directly is not what I'm trying to do, I'm trying to write the Player sub-class and use that instead:
Player.h:
class Player:public Entity {
Player() {
entity_sprite = Sprite("res/wildcard.png", { 0,0,36,63 }, { 36,63 });
}
};
Now I'm once again not able to directly assign arguments to the object directly, because the call of an object of a class type without appropriate operator() or conversion function to pointer-to-function type (Interestingly enough if I go back to the Entity object and assign the arguments there and pretend the errors don't exist, the error produced by the Player class changes to Too many arguments' and 'Too many initializers
This is getting too confusing.
Nonetheless, I am once again able to get around it using assignment, exactly the same as before, except this time I get an error saying the default constructor "Entity" cannot be referenced -- its a deleted function., so I go back to the Entity class and add an empty constructor like this: Entity() { } but then this constructor gives me another error saying no default constructor exists for class "Sprite", even though the Entity class doesn't exactly inherit from the Sprite class, so I go back even further to the Sprite class and give that an empty constructor: Sprite(){}, and the errors seemingly disappear, that is until I declare a Player object in the main.cpp file and try to compile and get a debug error pointing to the following line in AssetManager.cpp: assert(sInstance == nullptr);
So many problems for such a seemingly simple task, how do I pull myself out of this?
Ok, after consulting the SFML Forums, I have refactored the code to the following:
Sprite.h:
#include "AssetManager.h"
class Sprite{
public:
sf::Sprite m_sprite;
sf::Vector2f sprite_scale;
sf::Vector2u original_size;
sf::Vector2f texture_size;
Sprite(){}
sf::Sprite set_sprite(sf::Texture& tx, sf::IntRect rect, sf::Vector2f size);
};
Sprite.cpp:
#include "Sprite.h"
sf::Sprite Sprite::set_sprite(sf::Texture& tx, sf::IntRect rect, sf::Vector2f size) {
sf::Sprite spr(tx);
spr.setTextureRect(rect);
original_size =tx.getSize();
texture_size.x = static_cast<float>(original_size.x);
texture_size.y = static_cast<float>(original_size.y);
sprite_scale.x = size.x / texture_size.x;
sprite_scale.y = size.y / texture_size.y;
spr.setScale(sf::Vector2f(sprite_scale.x, sprite_scale.y));
spr.setOrigin(sf::Vector2f(original_size.x / 2, original_size.y / 2));
return spr;
}
Entity.h:
#pragma once
#include "Sprite.h"
#include "collision.h"
#include "Timer.h"
class Entity {
public:
Sprite spr;
sf::Sprite entity_sprite;
int health;
float max_speed;
sf::Vector2f speed;
sf::Vector2f direction;
float acceleration;
bool collision = false;
timer t;
float acc_time;
};
Player.h:
#pragma once
#include "Entity.h"
class Player:public Entity {
public:
Player();
float acc_time = t.accumulate_time();
void keyboard_controls();
void mouse_controls(sf::Vector2f cursor);
};
Player.cpp:
#include "Player.h"
#include <math.h>
Player::Player() {
speed = { 0,0 };
acceleration = 2;
max_speed = 500 + acceleration;
entity_sprite = spr.set_sprite(AssetManager::LoadTexture("res/wildcard.png"), { 0,0,60,63 }, { 60,63 });
}
In short, the Sprite class' constructor is replaced with a method that has the same exact role, that way I can simply declare a Sprite object with no parameters inside the Entity class, and I won't have any issues with the derived Player class since I won't be asked to create default constructors for both the Sprite and Entity classes.

Cannot get class data in box2d collision callback

I'm building a simple 2D game in C++ and am using Box2D for collision detection.
I have an Entity class from which an Enemy and Bullet class is derived, and an EnemySquare class is derived from the Enemy class.
I'm trying to detect collisions between the EnemySquare class and the Bullet class (will have more collision combinations to process later in development). To do this I have created a CollisionManager class deriving from the Box2D class b2ContactListener which handles the collision callbacks.
Each Entity instance has a private variable m_collisionObjectType which is an enum class of object types (shown below).
In the BeginContact() callback, I'm trying to cast the box2d fixture's user data to the correct class type so I can apply damage, mark bullets for removal etc.
(non-relevant code removed for simplicity)
Object Type Enum:
enum class COLLISION_OBJECT_TYPE {BULLET, ENEMY, PLAYER};
Entity class
.h
class Entity
{
public:
Entity();
~Entity();
COLLISION_OBJECT_TYPE getCollisionObjectType() { return m_collisionObjectType; }
protected:
b2Body* m_body = nullptr;
b2Fixture* m_fixtures[3];
COLLISION_OBJECT_TYPE m_collisionObjectType;
};
Enemy Class
.h
class Enemy : public Entity
{
public:
Enemy();
~Enemy();
virtual void init(glm::vec2 position, float health, float speed, Player* player, b2World* physicsWorld) = 0;
virtual void update(float deltaTime) = 0;
protected:
float m_health;
float m_speed;
Player* m_playerTarget;
};
Enemy Square Class
.h
class EnemySquare : public Enemy
{
public:
EnemySquare();
~EnemySquare();
void init(glm::vec2 position, float health, float speed, Player* player, b2World* physicsWorld) override;
void update(float deltaTime) override;
};
.cpp
void EnemySquare::init(glm::vec2 position, float health, float speed, Player * player, b2World* physicsWorld) {
// init physics body
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(m_position.x, m_position.y);
bodyDef.fixedRotation = false;
bodyDef.angle = 0;
bodyDef.userData = this;
m_body = physicsWorld->CreateBody(&bodyDef);
// init physics fixtures
b2PolygonShape squareShape;
squareShape.SetAsBox(m_width * 0.5f, m_height * 0.5f);
b2FixtureDef fixtureDef;
fixtureDef.shape = &squareShape;
m_fixtures[0] = m_body->CreateFixture(&fixtureDef);
}
Bullet Class
.h
class Bullet : public Entity
{
public:
Bullet(
b2World* world,
glm::vec2 startPosition,
glm::vec2 direction,
Tempest::glTexture texture,
float width,
float height,
float damage,
float speed,
float range
);
~Bullet();
// methods are unrelated
private:
// private variables are unrelated
};
.cpp
Bullet::Bullet(
b2World* world,
glm::vec2 startPosition,
glm::vec2 direction,
Tempest::glTexture texture,
float width,
float height,
float damage,
float speed,
float range
) {
// Make the body
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(m_position.x, m_position.y);
bodyDef.fixedRotation = true;
bodyDef.angle = 0;
bodyDef.userData = this;
m_body = world->CreateBody(&bodyDef);
// Create the box
b2PolygonShape boxShape;
boxShape.SetAsBox(m_height * 0.4f, m_width * 0.5f);
b2FixtureDef boxDef;
boxDef.shape = &boxShape;
m_fixtures[0] = m_body->CreateFixture(&boxDef);
m_collided = false;
m_collisionObjectType = COLLISION_OBJECT_TYPE::BULLET;
}
In my the CollisionManager class I'm trying to retrieve the colliding fixture's userData (which is a void*) then cast it to an Entity* to call the getCollisionObjectType() method. When I know what type of entity I'm dealing with I then want to cast it to the correct object type and do things like apply damage, mark bullets for removal etc. Code below:
void CollisionManager::BeginContact(b2Contact * contact) {
void* fixtureABodyData = contact->GetFixtureA()->GetBody()->GetUserData();
void* fixtureBBodyData = contact->GetFixtureB()->GetBody()->GetUserData();
if (fixtureABodyData && fixtureBBodyData) {
Entity* fixtureAData = static_cast<Entity*>(fixtureABodyData);
Entity* fixtureBData = static_cast<Entity*>(fixtureBBodyData);
if (fixtureAData->getCollisionObjectType() == COLLISION_OBJECT_TYPE::BULLET) {
std::cout << "A BULLET" << std::endl;
}
if (fixtureBData->getCollisionObjectType() == COLLISION_OBJECT_TYPE::BULLET) {
std::cout << "B BULLET" << std::endl;
}
if (fixtureAData->getCollisionObjectType() == COLLISION_OBJECT_TYPE::ENEMY) {
std::cout << "A ENEMY" << std::endl;
}
if (fixtureBData->getCollisionObjectType() == COLLISION_OBJECT_TYPE::ENEMY) {
std::cout << "B ENEMY" << std::endl;
}
std::cout << "----------------------" << std::endl;
}
}
For some reason, the casting works for the Bullet class but not for the Enemy class. I think it returns a nullptr. So I know one of the colliding bodies is a bullet, but I can't tell what the second body is.
I have a feeling I'm doing something wrong with the static_cast calls or it might be because the EnemySquare class is twice removed from the Entity class? or I could be doing something wrong in the Box2D code. Any advice would be appreciated!
Set the m_collisionObjectType member variable for the Enemy derived class. Preferably to COLLISION_OBJECT_TYPE::ENEMY.
As the code appears now, it's only setting m_collisionObjectType in the code for the Bullet derived class. So the Enemy derived class instances are getting constructed with their m_collisionObjectType member variables uninitialized. I.e. the value out of the getCollisionObjectType() method could be whatever was in the memory location of m_collisionObjectType before it got used by the constructor.
Hope this helps!

c++ structs as private data member

I have a project using the CImg library. What I have to do is declare classes that inherit from an abstract base class called shape. These classes are classes for the different shapes(circle, rectangle .. etc). What I want to do is use a struct class called point for the different points that I need for every class. So for example, for a triangle shape, I have to use three points to draw a triangle with each point having an x coordinate and a y-coordinate. So here's what I got so far.
class Shape
{
public:
virtual void draw_shape() = 0;
virtual double area() = 0;
};
struct Point
{
const int x; //const is necessary because CImg drawing functions require them.
const int y;
};
class Triangle : public Shape
{
private:
struct Point first;
struct Point second;
struct Point third;
public:
Triangle();
Triangle(const int, const int, const int, const int, const int, const int);
virtual void draw_shape();
virtual double area();
};
1) How do I initialize the x-coordinate and y-coordinate of each struct ?
Triangle::Triangle() : first.x(0), first.y(0), second.x(0), second.y(0), third.x(0), third.y(0)
does not work
2) Is my overloaded constructor correct or should I use this constructor:
Triangle(Point, Point, Point);
3) How do i use the points after this whenever I want to draw something ?!
4) Is the struct before instantiating the Points necessary in c++?
You can invoke the constructors of your points, like this:
Triangle() : first{0, 0}, second{0, 0}, third{0, 0} {}
You can add an explicit constructor yourself, if you wanted to do something a little more complex:
struct Point
{
int x;
int y;
Point(int a, int b) : x(a), y(b) { /* ... */ }
};
Considering 1)
You can simply use this:
Triangle::Triangle() : first{0,0}, second{0,0}, third{0,0} {}
Considering 2)
I think that the constructor
Triangle(Point, Point, Point);
is better. When you already have points, why not using them?
Considering 3)
dependons on how things get drawn
Considering 4)
No, it is not necessary.

c++ polymorphism - accessing inhertied variables

playersystem and rocketsystem inherit from system, playersystem contains pointer to rocketsystem. im getting an error when i try to access anything that is in system that rocketsystem is supposed to inherit. the runtime error is "expression cannot be evaluated" i set a breakpoint in visual studio, hovered the mouse over the position vector and it said that.
edit: for posterity this is what i was doing, and it turns out it is working, i was just setting th rocketsystem pointer to null for some reason
class Vector2D
{
public:
float x;
float y;
Vector2D(float x_, float y_) :x(x_),y(y_){}
};
class System
{
protected:
vector<Vector2D> position;
public:
void addEntity(Vector2D newPos)
{
position.push_back(newPos);
}
};
class projectile :public System
{
public:
void createRocket(Vector2D pos)
{
addEntity(pos);
}
};
class player : public System
{
public:
projectile* rocketSystem;
void init(projectile* rocketsys){rocketSystem = rocketsys;}
void fireRocket(Vector2D pos)
{
rocketSystem->createRocket(pos);
}
};
int main (int argc, char * const argv[])
{
player* PlayerSystem = new player;
projectile* RocketSystem = new projectile;
PlayerSystem->init(RocketSystem);
PlayerSystem->fireRocket(Vector2D(0,0));
return 0;
}
I'm going to use my psychic powers and guess that the System class doesn't have a createRocket() member. Since playersystem has a System *rocketSystem and not a rocketsystem *rocketSystem, the only functions that can be invoked on the rocketSystem member are those declared in the System class. It has to be a rocketsystem* if you want to be able to call that function, and the rocketsystem class has to be declared before the playersystem::fireRocket function is defined.

Object's structure overriding defined methods?

I have a class called Object:
class Object {
public:
Vector pos;
float emittance;
Vector diffuse;
virtual float intersection(Ray&) {};
virtual Vector getNormal(Vector&) {};
};
And another class which inherits it:
class Sphere: public Object {
public:
float radius;
virtual float intersection(Ray &ray) {
Vector distance;
float b, c, d;
distance = ray.origin - pos;
b = distance.dot(ray.direction);
c = distance.dot(distance) - radius*radius;
d = b*b - c;
cout << -b - sqrt(d);
if (d > 0.0) {
return -b - sqrt(d);
} else {
return false;
}
}
virtual Vector getNormal(Vector position) {
return (position - pos).norm();
}
};
When I compiled the program, I was expecting it to start spitting out tons and tons of lines of text. But for some reason, that whole method (the intersection() method) is never actually called at all!
Why is my intersection() function from the Sphere class not overriding the default on found in the Object class?
You did not declare the function as virtual and make sure that the method signature matches. Change it to:
class Object{
virtual float intersection(Ray) {};
virtual Vector getNormal(Vector) {};
}
class Sphere: public Object {
...
virtual float intersection(Ray ray) {
...
Firstly, the derived class takes a reference, and the Object class does not. Secondly, the Object declares them as non-const, and the Sphere defines them as const. These both mean that you're not actually overriding the same function.