C++ help writing a class with declaration on header file - c++

Well, hi there.
I'm new to c++ and I'm having some issues that I'm not sure what is causing them.
This is my main:
#include "GameWindow.h"
int main(void)
{
GameWindow * game_window = new GameWindow(true);
/* loop the game */
while (game_window->GetRunning())
{
// update
game_window->Update();
// draw
game_window->Draw();
}
delete game_window;
return 0;
}
and this is my header:
class GameWindow
{
private:
bool _running;
//GLFWwindow* _window;
public:
void SetRunning(bool new_val);
bool GetRunning();
GameWindow(bool running);
void Draw();
void Update();
}
and my c++ file:
#include "GameWindow.h"
void GameWindow::SetRunning(bool new_val)
{
_running = new_val;
}
bool GameWindow::GetRunning()
{
return _running;
}
GameWindow::GameWindow(bool running) :
_running(running)
{
}
void GameWindow::Draw()
{
}
void GameWindow::Update()
{
}
While going through all of this I find it tough to find why Visual Studio refuse to compile this code.
It's raising errors about how 'SetRunning' is overloading a function which differs only in return values, and that the return type of main should be Int and not GameWindow, and with all of this I just went completely lost.
Tried to put 'SetRunning' as a comment to simplify the issue but instead it raised the same on 'GetRunning' instead.
I'm guessing it's a really stupid mistake that is easy to fix, but still, can't find it.
Thank you for your time, and I'll appreciate any kind of help.

Missing ; at the end of class definition.
class GameWindow
{
// .....
}; // Missing semi-colon

Missing ; in class defination
{
};
because of this when you include the file in program then compiler not found the end of the class hence it says return type of main should be int not GameWindow

Related

Call class from other class with multiple variables

I am really stuck at this problem for two days now. I know I am missing some crutial information but I don't know what.
I am programming an ESP32 using vscode and platformio.
I have imported ezButton and ezOutput. They both work fine when I call them from main.cpp. I assume this is because I am not calling them from inside a different class. Now I wrote a custom class which does some stuff and I want to read inputs from ezButton and write outputs to ezOutput.
Where my head is stuck at at this point is that I don't now how to correctly initialize the classes correctly.
I imagine it working like in my main.cpp where I for example just type inputPinName.isPressed();and I get my information. This should also work the other way like outputPinName.high();.
I would really appreciate someone explaining this to me or providing a link to a resource that explains this issue.
Here are some code snippets:
main.cpp
#include <ezButton.h>
#include <ezOutput.h>
// INPUTS
ezButton inputPinUp(34, INPUT_PULLDOWN);
//... same for all other inputs
// OUTPUTS
ezOutput outputPinUp(4);
ezOutput outputPinDown(0);
#define DEBOUNCE_TIME 50
void setup()
{
inputPinUp.setDebounceTime(DEBOUNCE_TIME);
//... same for all other pins
}
void loop()
{
inputPinUp.loop();
//... same for all other pins
}
shutter.h
#include <ezButton.h>
#include <ezOutput.h>
class shutter
{
private:
int inputPinUp;
//...
int _outUp;
int _outDown;
ezButton Button_;
ezOutput Output_;
public:
shutter(ezOutput& outputPin) : Output_(outputPin) {} //ERROR: no default constructor exists for class "ezButton"
shutter(ezButton& Pin) : Button_(Pin) {} //ERROR: no default constructor exists for class "ezOutput"
void shutterInput(
int inputPinUp,...);
void shutterOutput(
int outputPinUp,
int outputPinDown);
void stop(void);
void driveUp(void);
void driveDown(void);
};
I didn't switch the error messages above. They are actually reversed somehow.
shutter.cpp
#include "shutter.h"
//...
void shutter::shutterOutput(
int outputPinUp,
int outputPinDown)
{
int _outUp = outputPinUp; //I am not sure if I even have to do this
}
void shutter::stop(void)
{
ezOutput _outUp.low(); //ERROR: no default constructor exists for class "ezOutput"
digitalWrite(_outDown, LOW);
_moving = false;
}

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
}

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

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

Getting an undefined reference error

I am hoping someone can point me in the right direction to figure out why I am getting the following error:
$~/display/triangleDisplayable.cc:4: undefined reference to `Displayable::Displayable()'
I am trying to abstract a class Displayable and have a class triangleDisplayable that implements its methods. The two header files I have are "Displayable.h":
class Displayable {
public:
Displayable();
virtual int getSizeOfArrays() = 0;
void display(int size);
private:
virtual void init() = 0;
virtual int getSizeOfPointsArray() = 0;
virtual int getSizeOfNormalsArray() = 0;
};
and "triangleDisplayable.h"
#include "Displayable.h"
class triangleDisplayable : public Displayable
{
public:
triangleDisplayable();
int getSizeOfArrays();
private:
void init();
int getSizeOfPointsArray();
int getSizeOfNormalsArray();
};
And then I have "Displayable.cc"
#include <iostream>
#include "Displayable.h"
Displayable::Displayable() {
std::cout << "testing Displayable constructor" << std::endl;
}
void Displayable:display(int size) {
}
int main () {
return 0;
}
and "triangleDisplayable.cc"
#include <iostream>
#include "triangleDisplayable.h"
triangleDisplayable::triangleDisplayable() : Displayable() {
}
int triangleDisplayable::getSizeOfArrays() {
return 0;
}
void triangleDisplayable::init() {
}
int triangleDisplayable::getSizeOfPointsArray() {
return 0;
}
int triangleDisplayable::getSizeOfNormalsArray() {
return 0;
}
int main () {
return 0;
}
I have been trying to follow along with various tutorials to learn how to do abstraction in C++, but I have not really been able to find any helpful solutions to this. I believe that all of my #includes are correct, which I read is a common problem. The error message seems to indicate that the problem is the line
triangleDisplayable::triangleDisplayable() : Displayable() {
}
I have tried to compile without the : Displayable() but I get the same error. Is there perhaps a problem with my syntax in my header files?
No, the error is in tool invocation. You need to link the two source files together (e.g. g++ -o foo a.cc b.cc). And remove one of the main functions, as you can't have two different ones.