Why this function variable only works if it's static? - c++

I'm trying to put a bunch of sounds in a std::vector because it's very convenient.
I'm using an auxiliary variable called laser, load the sound into it and, if it's everything ok, push_back into the vector.
When I try to play any the sound, nothing happens, not even error messages which should be printed if anything goes wrong.
Just for curiosity I made laser static and voilá, it works flawlessly (or it seems to).
I'd like to know why.
Header file:
// audio_system.h
#ifndef KUGE_HEADERS_AUDIO_SYSTEM_H_
#define KUGE_HEADERS_AUDIO_SYSTEM_H_
#include "event.h"
#include "system.h"
#include "../sdl2_wrappers/sdl2_wrappers.h"
#include "../include/resources_path.h"
#include <vector>
namespace kuge {
class AudioSystem : virtual public System {
public:
AudioSystem(EventBus& bus): System(bus) {}
void handleEvent(const Event& event);
static bool loadResources();
private:
static void generateRandomSequence();
static std::vector<ktp::SDL2_Sound> lasers_;
};
} // end namespace kuge
#endif // KUGE_HEADERS_AUDIO_SYSTEM_H_
cpp file:
#include "event_bus.h"
#include "audio_system.h"
std::vector<ktp::SDL2_Sound> kuge::AudioSystem::lasers_{};
void kuge::AudioSystem::generateRandomSequence() {}
void kuge::AudioSystem::handleEvent(const Event& event) {
switch (event.getType()) {
case EventTypes::LaserFired:
if (lasers_[0].play() == -1) {
ktp::logSDLError("laser_.play");
}
break;
default:
break;
}
}
bool kuge::AudioSystem::loadResources() {
static ktp::SDL2_Sound laser{}; // here! If I don't make this static, nothing happens
if (!laser.loadSound(ktp::getResourcesPath() + "sounds/laser2.wav")) {
return false;
} else {
lasers_.push_back(laser);
}
ktp::logMessage("AudioSystem: resources loaded.");
return true;
}

OK, so following the advices from the comments, I've made the following changes to make ktp::SDL2_Sound class follow the rule of 0 and now it works without the need to set the laser variable to static. This solves the problem, but I'm still not sure why it worked being static.
class SDL2_Sound {
public:
//~SDL2_Sound() { free(); } // now I don't need any destructor
bool loadSound(const std::string& path);
int play(int loops = 0);
private:
void free();
// Mix_Chunk* sound_ = nullptr; // old raw pointer
std::shared_ptr<Mix_Chunk> sound_{};
};
/* void ktp::SDL2_Sound::free() {
if (sound_ != nullptr) {
Mix_FreeChunk(sound_);
sound_ = nullptr;
}
} */
bool ktp::SDL2_Sound::loadSound(const std::string& path) {
//free();
sound_.reset(Mix_LoadWAV(path.c_str()), &Mix_FreeChunk);
//sound_ = Mix_LoadWAV(path.c_str());
if (sound_ == nullptr) {
ktp::logSDLError("Mix_LoadWAV", path);
return false;
}
return true;
}

Related

Proper way to handle wxwidget events with std::thread

Been trying to figure out how to properly handle custom events in conjunction with std::thread, haven't been able to find any code without wxThread. As i understand i need to use wxQueueEvent, but my problem is how to get the wxEvtHandler pointer to the class holding the thread. The bellow code passes a pointer of the class where i have the "onErrorEvent" function, this compiles and works, but I'm not sure if that's a "legal" way of doing it. It feels like a bad idea to use the pointer that way idk. All i want to know is if it will work hehe, doesn't need to be perfect textbook worthy code.
#include "cMain.h"
#include <iostream>
#include <thread>
using namespace std;
const int myEvtId=10000;
const int writeEvtId=10001;
wxDEFINE_EVENT(MY_EVT,wxCommandEvent);
wxDEFINE_EVENT(WRITE_EVT,wxCommandEvent);
wxBEGIN_EVENT_TABLE(cMain,wxFrame)
EVT_COMMAND(myEvtId,MY_EVT,cMain::onErrorEvent)
EVT_COMMAND(writeEvtId,WRITE_EVT,cMain::onWriteEvent)
wxEND_EVENT_TABLE()
class threadClass
{
public:
void startThread(wxEvtHandler *evtHandle)
{
threadState=true;
thr=thread(&threadClass::threadFn,this,evtHandle);
}
void endThread()
{
if(threadState)
{
threadState=false;
thr.join();
}
}
private:
bool threadFn(wxEvtHandler *evtHandle)
{
while(threadState)
{
if(error)
{
//Error occurred
wxCommandEvent *evt=new wxCommandEvent(MY_EVT,myEvtId);
wxQueueEvent(evtHandle,evt);
return false;
}
else
{
//Otherwise write data
wxCommandEvent *evt=new wxCommandEvent(WRITE_EVT,writeEvtId);
evt->SetString("Data to be written");
wxQueueEvent(evtHandle,evt);
}
this_thread::sleep_for(chrono::milliseconds(500));
}
return true;
}
private:
thread thr;
bool threadState=false;
bool error=false;
};
threadClass thrClass;
cMain::cMain() : wxFrame(nullptr,wxID_ANY,"wxWidgets template",wxPoint(30,30),wxSize(420,520))
{
txt1=new wxTextCtrl(this,wxID_ANY,"",wxPoint(20,20),wxSize(300,400),wxTE_READONLY | wxTE_MULTILINE);
wxButton *btn1=new wxButton(this,wxID_ANY,"Button 1",wxPoint(160,430),wxSize(80,40));
thrClass.startThread(this);
}
cMain::~cMain()
{
thrClass.endThread();
}
void cMain::onErrorEvent(wxCommandEvent &evt)
{
//Handle Error
thrClass.endThread();
}
void cMain::onWriteEvent(wxCommandEvent &evt)
{
//Write data
txt1->AppendText(evt.GetString()+'\n');
}
I'm using std:thread so it's compatible with existing code I've already written, so I'd rather not rewrite it with wxThread instead.
//Benji
**Edit - I revised the code to include my method of printing to the textCtrl ui element.

C++ passing class to constructor = not passing same instance?

It seems that, when I pass an class it is not passing a persistant (the same) instance of that class as I would expect. I'm assuming this has something to do with memory state but I would appreciate it if someone could explain exactly what is happening. The issue is easily demonstrated as follows :
Main.ino
#include "Debug.h"
#include "Box.h"
Debug debug;
Box box(debug);
void loop(){
debug.message("loop");
debug.line();
}
void setup(){
debug.init();
box.init();
debug.message("Setup Complete");
debug.line();
}
Debug.h
#ifndef DEBUG_H
#define DEBUG_H
class Debug {
private:
bool state;
public:
Debug();
void init();
void message(const char *str);
void message(int);
void line();
};
#endif
Debug.cpp
#include "Debug.h"
#include <Arduino.h>
Debug::Debug() : state(false) {}
void Debug::init() {
if (state == false){
Serial.begin(9600);
state = true;
}
}
void Debug::message(const char *messageChar) {
if (state){
const char *p;
p = messageChar;
while (*p) {
Serial.print(*p);
p++;
}
}
}
void Debug::message(int messageInt) {
if (state){
Serial.print(messageInt);
}
}
void Debug::line() {
if (state){
Serial.println();
}
}
Box.h
#ifndef BOX_H
#define BOX_H
#include "Debug.h"
class Box {
private:
Debug debug;
public:
Box(Debug &debug);
void init();
};
#endif
Box.cpp
#include "Box.h"
#include <Arduino.h>
Box::Box(Debug &debug):
debug(debug)
{}
void Box::init(){
// Switches
pinMode(28, INPUT_PULLUP);
debug.message("Box intialized");
debug.line();
}
So the above code outputs to serial:
Setup Complete
If I modify Box::init() to
void Box::init(){
// Switches
pinMode(28, INPUT_PULLUP);
debug.init();
debug.message("Box intialized");
debug.line();
}
I get what I want :
Box initialized
Setup Complete
If I get rid of Box constructor class and instead do
void Box::init(Debug &debug){
this->debug = debug;
// Switches
pinMode(28, INPUT_PULLUP);
debug.message("Box intialized");
debug.line();
}
Called via Main.ino like
void setup(){
debug.init();
box.init(debug);
debug.message("Setup Complete");
debug.line();
}
I get the desired response again. I don't understand why my first attempt doesn't work nor do I feel comfortable knowing what best practices are. I would appreciate any guidance.
You have two Debug values in your code. One global, one member of the Box class.
Those are two distinct values, since Box create or copy from a value to create its own, and there's the global one.
A solution would be to contain a reference or a pointer.
Here's the example with a reference:
class Box {
private:
Debug& debug;
// ^---- there
public:
Box(Debug &debug);
void init();
};
If you want Box to still be assignable, then use a pointer:
class Box {
private:
Debug* debug;
// ^---- now it's a star
public:
Box(Debug &debug);
void init();
};
Box::Box(Debug &debug):
debug(&debug)
{} // ^----- here, we take the address of the debug variable.
Since references are immutable, you loose some important feature of the language: assignment.
struct thing {
int& ref;
};
int main () {
int a, b;
thing t1{a}, t2{b};
t1 = t2; // ERROR!
}
The assignment would cause t1.ref to point to b after the assignment.
Pointer has a more difficult syntax and hard to guess semantics. However, they play very well with assignment since they give you more freedom:
struct thing {
int* ptr;
};
int main () {
int a, b;
thing t1{&a}, t2{&b};
t1 = t2; // Works, t1.ptr points to b
}

c++ [gamestate] function does not take in correct argument error

Hello i have problem of compile my code
i follow http://gamedevgeek.com/tutorials/managing-game-states-in-c/ tutorial
but it fail to compile and i don't know why.
the error msg from visual studio
here is my code
the CGameEngine modify code
#include <vector>
#include "GameState.h"
#include "GameEngine.h"
class GameState;
class GameStateManager
{
public:
GameStateManager(GameEngine* engine, MSG * msg);
~GameStateManager();
void Cleanup();
void ChangeState(GameState* state);
void Update();
bool Running() { return m_running; }
void Quit();
private:
std::vector<GameState *> states;
bool m_running;
GameEngine * m_engine;
MSG *m_msg;
};
#include "GameStateManager.h"
GameStateManager::GameStateManager(GameEngine* engine, MSG * msg)
:m_engine{ engine }, m_msg{ msg }, m_running{ true }
{
}
GameStateManager::~GameStateManager()
{
}
void GameStateManager::Cleanup()
{
while (!states.empty()) {
states.back()->Exit();
states.pop_back();
}
}
void GameStateManager::Quit()
{
m_running = false;
m_msg->message = WM_QUIT;
}
void GameStateManager::ChangeState(GameState* state)
{
if (!states.empty()) {
states.back()->Exit();
states.pop_back();
}
states.push_back(state);
states.back()->Enter(m_engine, m_msg);
}
void GameStateManager::Update()
{
states.back()->Update(this);
}
the CGameState modify code
#include "GameStateManager.h"
class GameState
{
public:
GameState() {}
virtual ~GameState() {}
virtual void Enter(GameEngine * , MSG * ) = 0;
virtual void Update(GameStateManager* game) =0;
virtual void Exit() = 0;
};
one of the state class
#include "MainMenu.h"
class Logo :public GameState
{
public:
Logo();
~Logo();
static Logo* Instance()
{
return &m_Logo;
}
void Enter(GameEngine * engine, MSG * msg);
void Update(GameStateManager* game);
void Exit();
private:
static Logo m_Logo;
};
#include "Logo.h"
Logo::Logo()
{
}
Logo::~Logo()
{
}
void Logo::Enter(GameEngine * engine, MSG * msg)
{
m_GameEngine_Info = engine;
m_msg = msg;
}
void Logo::Update(GameStateManager* game)
{
}
void Logo::Exit()
{
}
i get no compile error when editing the code, but when i try compile it get this error.
You have circular includes. Use include guards and replace
#include "GameStateManager.h"
with
class GameStateManager;
in GameState.h. Move this include into GameState.cpp.
Do similar with #include "GameEngine.h" and #include "GameState.h" in GameStateManager.h and GameStateManager.cpp.

One or more multiply defined symbols found, error LNK1169 C++

Sorry for the lack of a descriptive title.
I'm getting an error "one or more multiply defined symbols found"; to be more specific, I'm getting 46 of them. One for each function in my header/source files. Using Visual Studios 2013.
Here is the relevant source code:
augments.h
#ifndef AUGMENTS_H_
#define AUGMENTS_H_
namespace Augments {
// only used for pass-ins for constructors
enum class Weapon_Type {
sword
};
enum class Head_Type {
head
};
enum class Body_Type {
body
};
// the player (Monster) has a head, body and weapon
// that augments his abilities. This will mostly
// be the thing that draws to the screen for each
// augmentation, but more importantly it contains
// specific statistics about each one.
// So if there was a body that was able to fly,
// there would be a bool that denotes this ability.
class Head : public Actor {
const Head_Type type;
public:
Head(Head_Type);
void Update(float dt);
};
class Body : public Actor {
const Body_Type type;
public:
Body(Body_Type);
void Update(float dt);
};
class Weapon : public Actor {
const Weapon_Type type;
public:
Weapon(Weapon_Type);
void Update(float dt);
};
}
using AugHead = Augments::Head;
using AugBody = Augments::Body;
using AugWep = Augments::Weapon;
#endif
augments.cpp
#include "stdafx.h"
#include "Angel.h"
#include "Augments.h"
#include "LD33.h"
Augments::Head::Head(Augments::Head_Type x) : type(x) {
switch ( x ) {
case Head_Type::head:
SetSprite("Images\\head.png");
break;
};
};
void Augments::Head::Update(float dt) {
SetPosition(Game::thePlayer->GetPosition().X,
Game::thePlayer->GetPosition().Y-
MathUtil::ScreenToWorld(Vec2i(0,40)).Y);
};
Augments::Body::Body(Augments::Body_Type x) : type(x) {
switch ( x ) {
case Body_Type::body:
SetSprite("Images\\body.png");
break;
};
}
void Augments::Body::Update(float dt) {
SetPosition(Game::thePlayer->GetPosition().X,
Game::thePlayer->GetPosition().Y);
}
Augments::Weapon::Weapon(Augments::Weapon_Type x ) : type(x) {
switch ( x ) {
case Weapon_Type::sword:
SetSprite("Images\\weapon.png");
break;
}
}
void Augments::Weapon::Update(float dt) {
SetPosition(Game::thePlayer->GetPosition().X,
Game::thePlayer->GetPosition().Y-
MathUtil::ScreenToWorld(Vec2i(0,-40)).Y);
}
monster.h
// monster related
#include "Augments.h"
#include "Angel.h"
#ifndef MONSTER_H_
#define MONSTER_H_
namespace Player {
// contains information like health attack etc
// but more important body types
class Monster : public PhysicsActor {
int max_health, curr_health;
int attack_damage;
Augments::Head* frame_head;
Augments::Weapon* frame_weapon;
Augments::Body* frame_body;
public:
void Refresh(float dt);
int R_Max_Health() const;
int R_Curr_Health() const;
int R_Attack_Damage() const;
Augments::Head* R_Frame_Head();
Augments::Weapon* R_Frame_Weapon();
Augments::Body* R_Frame_Body();
void Set_Max_Health(int);
void Set_Curr_Health(int);
void Add_Curr_Health(int);
void Set_Attack_Damage(int);
// will automatically remove old
// actors from the stage and deallocate
void Set_Frame_Head(Augments::Head_Type);
void Set_Frame_Weapon(Augments::Weapon_Type);
void Set_Frame_Body(Augments::Body_Type);
Monster(Augments::Head_Type,
Augments::Weapon_Type,
Augments::Body_Type);
};
};
using PlMonster = Player::Monster;
#endif
monster.cpp
#include "stdafx.h"
#include "Monster.h"
#include "Augments.h"
#include "Angel.h"
void Player::Monster::Refresh(float dt) {
};
int Player::Monster::R_Max_Health() const { return max_health; }
int Player::Monster::R_Curr_Health() const { return curr_health; }
int Player::Monster::R_Attack_Damage() const { return attack_damage; }
Augments::Head* Player::Monster::R_Frame_Head() { return frame_head; }
Augments::Body* Player::Monster::R_Frame_Body() { return frame_body; }
Augments::Weapon* Player::Monster::R_Frame_Weapon() { return frame_weapon; }
void Player::Monster::Set_Max_Health(int x) { max_health = x; }
void Player::Monster::Set_Curr_Health(int x) { curr_health = x; }
void Player::Monster::Add_Curr_Health(int x) { curr_health += x; }
void Player::Monster::Set_Attack_Damage(int x) { attack_damage = x; }
void Player::Monster::Set_Frame_Head(Augments::Head_Type x) {
if ( frame_head != nullptr ) {
frame_head->Destroy();
delete frame_head;
frame_head = nullptr;
}
frame_head = new Augments::Head(x);
theWorld.Add(frame_head);
};
void Player::Monster::Set_Frame_Weapon(Augments::Weapon_Type x) {
if ( frame_weapon != nullptr ) {
theWorld.Remove(frame_weapon);
delete frame_weapon;
frame_weapon = nullptr;
}
frame_weapon = new Augments::Weapon(x);
theWorld.Add(frame_weapon);
};
void Player::Monster::Set_Frame_Body(Augments::Body_Type x) {
if ( frame_body != nullptr ) {
theWorld.Remove(frame_body);
delete frame_body;
frame_body = nullptr;
}
frame_body = new Augments::Body(x);
theWorld.Add(frame_body);
};
Player::Monster::Monster(Augments::Head_Type head,
Augments::Weapon_Type weapon,
Augments::Body_Type body) {
frame_body = nullptr;
frame_head = nullptr;
frame_weapon = nullptr;
Set_Frame_Body(body);
Set_Frame_Head(head);
Set_Frame_Weapon(weapon);
}
source.cpp
#include "stdafx.h"
#include "LD33.h"
#include "Angel.h"
int main ( ) {
Game::Initialize();
theWorld.StartGame();
theWorld.Destroy();
return 0;
}
Errors include things such as:
Error 43 error LNK2005: "public: int __thiscall Player::Monster::R_Attack_Damage(void)const " (?R_Attack_Damage#Monster#Player##QBEHXZ) already defined in Augments.obj C:\Users\The Shire\Desktop\ludum_dare\ludumdare33\Code\ClientGame\source.obj ClientGame
Error 3 error LNK2005: "public: void __thiscall Player::Monster::Set_Frame_Body(enum Augments::Body_Type)" (?Set_Frame_Body#Monster#Player##QAEXW4Body_Type#Augments###Z) already defined in Augments.obj C:\Users\The Shire\Desktop\ludum_dare\ludumdare33\Code\ClientGame\LD33.obj ClientGame
And it pretty much states similar for every single function in Monster.
Sorry for just dumping a ton of code. I've been trying to debug it for awhile but couldn't come up with any reasonable solution. I have the include guards, I don't see any namespace conflicts, and everything that needs to be defined is outside of the header files. I can't find anything in augments.h that would be causing this. I also thought it might be the enums, but replacing them with just int did not work either.
I'm thinking it might be the order of the include files? hmm. Maybe there's somehow multiple source files somewhere but I would have no clue as to how. Any help?
Had included Monster.cpp in another header file on accident! Oops

C++ DLL Class is crashing whilst creating a private member

I have a Problem and i am completely stuck.
First i show you the code:
Config for Building(NarviConfig.h):
#pragma once;
namespace Narvi
{
#ifdef NARVI_EXPORTS
#define _NarviExport __declspec(dllexport)
#else
#define _NarviExport __declspec(dllimport)
#endif
}
//-------------------------------------------
I have 2 Classes in a DLL like this:
The first One(NarviRoot.h):
Header:
#pragma once
#include "NarviConfig.h"
#include "NarviWindow.h"
namespace Narvi
{
class _NarviExport NarviRoot
{
public:
NarviRoot();
~NarviRoot();
public:
bool Init(void);
private:
NarviWindow* mWindow;
};
}
Source:-----------------------------
#include "NarviRoot.h"
namespace Narvi
{
NarviRoot::NarviRoot()
{
}
NarviRoot::~NarviRoot()
{
delete mWindow;
}
bool NarviRoot::Init(void)
{
mWindow = new NarviWindow();
return true;
}
}
//-----------------------------------------------------------------
The window(NarviWindow.h):
Header
#pragma once
#include "NarviConfig.h"
namespace Narvi
{
class _NarviExport NarviWindow
{
public:
NarviWindow();
~NarviWindow();
};
}
Source:--------------------------------
#include "NarviWindow.h"
namespace Narvi
{
NarviWindow::NarviWindow()
{
}
NarviWindow::~NarviWindow()
{
}
}
And this is my Testapp
mRoot = new Narvi::NarviRoot();
mRoot->Init();
It seems to work, but the program crashes when calling
mWindow = new NarviWindow();
Inside of
bool NarviRoot::Init(void)
{
mWindow = new NarviWindow();
return true;
}
and i can't figure out why.
If i write:
NarviWindow* mWindow = new NarviWindow();
it doesn't crash.
The constructor of NarviWindow is doing nothing, but it seems he can't access the private member mWindow.
I am pretty sure it is a simple error i made, but i can't see the wood for the trees.
Thank you! :)