I'm relatively new to c++ so I'm getting used to the scope of functions and variables in this environment. One issue I can't solve is being able to call a function defined in a subclass of a class which declares this function as pure virtual. Here's my class structure:
class Clock{
public:
virtual void Tick() = 0;
std::string Print();
//Mutators
int Seconds();
int Minutes();
int Hours();
void setTime(int secs, int mins, int hours);
//Accessors
int getSecs(){ return _secs; }
int getMins(){ return _mins; }
int getHrs(){ return _hours; }
private:
int _secs, _mins, _hours, _days = 0;
};
class NormalClock : public Clock{
public:
void Clock::Tick();
private:
};
class AlarmClock : public Clock{
public:
void Clock::Tick();
bool CheckAlarm();
void SetAlarmTime(int hrs, int mins, int secs);
int GetAHrs();
int GetAMins();
int GetASecs();
private:
int _alarmhrs, _alarmmins, _alarmsecs;
};
In my source file I want to define a body for the Tick() function in the AlarmClock class. But within this function I want to call the Tick() function from it's superclass, the NormalClock class. My issue is that when I do so without defining any objects to work off of, I can't call the superclass Tick() function as my IDE (VS2013) thinks I'm referring to the Tick()from the current class (the AlarmClock subclass). I looked around on the web and determined that it would probably require the use of the using keyword, but I've been unsuccessful in implementing it properly. Here's the function I'm trying to build for reference:
void AlarmClock::Tick(){
NormalClock::Clock::Tick();
if (this->CheckAlarm()){ cout << "\nAlarm! # " << this->Print() << "\n\n"; }
}
There's no errors in VS when calling the function as above, but the compiler complains of a static reference to a non-static member, which is understandable.
You were close, but your code has a few problems.
AlarmClock does not inherit from NormalClock
In AlarmClock::Tick call NormalClock::Tick() instead of NormalClock::Clock::Tick()
In NormalClock change Clock::Tick to Tick in your class declaration.
AlarmClock does not derive from NormalClock so you are calling the method statically (there is no instance of NormalClock to be used).
NormalClock::Clock::Tick();
looks a lot like you mean the right thing. Now make your AlarmClock actually inherit from NormalClock, and then just NormalClock::Tick() away :)
Thanks everyone, looks like it was a simple case of changing the base class declaration to NormalClockin the definition of the class AlarmClock. VS2013 was skipping over the NormalClock class and observing only the Tick() pure virtual function in Clock, which is why I couldn't call NormalClock::Tick() as intended in the body of the AlarmClock::Tick() function.
Related
I use a library which has these definitions
typedef void (*CallbackFunction) (ESPRotary&);
void ESPRotary::setChangedHandler(CallbackFunction f) { ... }
When I try to use the setChangedHandler function I get an issue that the definition of my callback is wrong.
#pragma once
#include "ESPRotary.h"
class MyUsermod : public Usermod
{
private:
ESPRotary r = ESPRotary(13, 12);
public:
void rotate(ESPRotary &r)
{
Serial.println(r.getPosition());
}
void setup()
{
// argument of type "void (MyUsermod::*)(ESPRotary &r)" is incompatible
// with parameter of type "ESPRotary::CallbackFunction"C/C++(167)
r.setChangedHandler(rotate);
}
};
What am I doing wrong?
The callback function needs to be defined statically when defined inside the class:
class MyUsermod : public Usermod
{
private:
ESPRotary r = ESPRotary(13, 12);
public:
/* Callback function "static" defined */
static void rotate(ESPRotary &r)
{
Serial.println(r.getPosition());
}
void setup()
{
r.setChangedHandler(rotate);
}
};
References
Why callback functions needs to be static when declared in class?
void rotate(ESPRotary &r)
This is not a function. This is a (non-static) class method. This is declared as a member of class MyUsermod, something that's completely different from declaring a function named rotate() is some randomly-chosen .cpp file, with no further context.
Class methods require instances of classes to be invoked for. The type of rotate is
void (MyUsermod::*) (ESPRotary&)
and not
void (*) (ESPRotary&)
and this answers the reason for the compilation error, and the type mismathc.
As far as how to fix it, there is no uniform solution for every instance of this issue. It depends entirely on how these objects are used in the rest of your program. The most flexible solution is to change CallbackFunction to be the correct type, and then decide whose class instance's method will be invoked in the code that invokes the callback.
I'm trying to do class inheritance in C++, but it obviously works very differently than in Python.
Right now, I have two classes, one called Player that is the base class, and another one called HumanPlayer that's the subclass.
The Player class is an abstract class that has two ways of working.
The first is that it acts like a singleton. It has one static function called make_move that people can call with an int and a TicTacToeGame&, and it will make a move for the player with that int as the player's number in that game of TicTacToe.
The second is that it works as a class for creating objects that have a player number as a property. So, if you construct an object with the class, you should get back an object with a player_number property. Then, if you call the make_move function with just a TicTacToeGame& on the object, it will automatically plug in its player number and use the static class method to make the move in the game.
I want the same functionality for HumanPlayer, except I just want to have to write a new static function for HumanPlayer, and that's it, since the other functionality remains the same.
Here's the code:
#include <iostream>
#include <string>
using namespace std;
class TicTacToeGame {
};
class Player {
public:
static void make_move(int player_number, TicTacToeGame& game);
protected:
int player_number;
public:
explicit Player(int player_number_param) {
player_number = player_number_param;
}
public:
void make_move(TicTacToeGame& game) {
return make_move(player_number, game);
}
};
class HumanPlayer: public Player {
public:
static void make_move(int player_number, TicTacToeGame& game) {}
public:
HumanPlayer(int player_number_param): Player(player_number_param) {}
};
int main()
{
TicTacToeGame game;
HumanPlayer human_player = HumanPlayer(2);
human_player.make_move(game);
return 0;
}
I learned recently that subclasses don't inherit constructors, so it turns out I have to write both a new static function and a constructor, which I have done.
However, whenever I initialize a new HumanPlayer object, the compiler can't seem to find a match for the make_move(TicTacToeGame&) method, and I'm not sure why.
The specific error message I'm getting is
C:\Users\London\Desktop\Python
Programs\LearningC++\FirstProgram_SO.cpp: In function 'int main()':
C:\Users\London\Desktop\Python
Programs\LearningC++\FirstProgram_SO.cpp:41:29: error: no matching
function for call to 'HumanPlayer::make_move(TicTacToeGame&)'
human_player.make_move(game); ^ C:\Users\London\Desktop\Python
Programs\LearningC++\FirstProgram_SO.cpp:29:15: note: candidate:
static void HumanPlayer::make_move(int, TicTacToeGame&) static void
make_move(int player_number, TicTacToeGame& game) {} ^~~~~
C:\Users\London\Desktop\Python
Programs\LearningC++\FirstProgram_SO.cpp:29:15: note: candidate
expects 2 arguments, 1 provided
How can I get the HumanPlayer class to work in the same way the Player class does?
The redefinition of the static function with the same name is hiding the one you want to use.
Either rename it differently or add
public:
using Player::make_move;
Note that unlike Java you don't need to repeat public: before every function, the same visibility applies as long as you don't change it.
class YourClass {
public:
void foo1(); // public
void bar1(); // also public
protected:
void foo2(); // protected
void bar2(); // also protected
};
Consider the following class:
//! Counter class base. Must be inherited.
class base_seeded_counter
{
public:
//! Destructor
virtual ~base_seeded_counter() { };
//! Get the next value.
int get_next();
protected:
//! Override the counter next value.
void set_next(const int next);
private:
int m_next_value; // Next value.
}
// ------------------------------------------------------
inline int base_seeded_counter::get_next()
{
return m_next_value++;
}
// ------------------------------------------------------
inline void base_seeded_counter::set_next(const int next)
{
m_next_value = next;
}
The purpose of this class is to implement a base counter object with the intention that it must be inherited. It does not have any virtual methods other than the destructor and, more importantly, does not initialize the m_next_value member. This is the job of the derived class. For example:
class file_seeded_counter : public base_seeded_counter
{
public:
file_seeded_counter(const std::string &file_name);
void reseed();
private:
std::string m_file_name;
}
inline int file_seeded_counter::file_seeded_counter(const std::string &file_name) :
m_file_name(file_name)
{
reseed();
}
inline void file_seeded_counter::reseed()
{
int seed_from_file;
// open file here and get seed value...
set_next(seed_from_file);
}
This class, deriving from base_seeded_counter reads the initial counter value from a file, and offers the ability to re-read the seed from the file via the reseed() method. There may be other classes that offer similar functionality to seed from databases, network sources, or a PRNG, for example.
My question is this: Given that I have no pure virtual methods, does C++ offer a mechanism to prevent someone from creating an instance of base_seeded_counter?
My question is this: Given that I have no pure virtual methods, does C++ offer a mechanism to prevent someone from creating an instance of base_seeded_counter?
Yes, give it a protected default constructor (may be empty).
Given that you already have a virtual destructor, the obvious way would be to declare it pure virtual. It's entirely legitimate to have a pure virtual destructor that's also defined in the base class:
class base_seeded_counter {
public:
virtual ~base_seeded_counter() = 0;
int get_next();
protected:
void set_next(const int next);
private:
int m_next_value;
}
inline virtual base_seeded_counter::~base_seeded_counter() {}
Defining the destructor this way doesn't change the fact that it's a pure virtual, so this class can't be instantiated.
As an aside, the comments you currently have in the code are 100% useless visual noise. A comment of get next on a function named get_next adds nothing useful at all.
I am new to c++ and currently learning inheritance. I am not sure how to properly inherit my abstract class MapItem, I keep receiving these errors ..
error snippet
hidden overloaded virtual function 'MapItem::tick' declared here:
different qualifiers (const vs none)
virtual void tick() const = 0;
Undefined symbols for architecture x86_64:
"Residential::Residential()"
It is also claiming that my class Residential is an abstract class.
The program only successfully compiles and runs when I add the const keyword to the tick() function. But quiet obviously, this is a problem because tick() needs to operate on some class member variables.
I properly included all the files and my make file is targeting all the correct files, which makes this error out of my understanding.
map_item.h
// abstract class
class MapItem {
...
virtual void tick() const = 0;
}
residential.h
#ifndef RESIDENTIAL_H
#define RESIDENTIAL_H
#include "map_item.h"
class Residential : public MapItem {
private:
int capacity;
double taxRevenue;
public:
Residential();
virtual ~Residential();
void tick();
double collectTaxes();
};
#endif
residential.cpp
#include "residential.h"
Residential::Residential() {
capacity = 1;
taxRevenue = 0.0;
}
Residential::~Residential() {}
void Residential::tick() {
}
double Residential::collectTaxes() {
taxRevenue = 0.0;
return taxRevenue;
}
Your problem's simply that in Residential you declare and define tick as follows:
void Residential::tick()
...while the abstract base has...
virtual void tick() const = 0;
You should add the const to Residential::tick, or remove it from Mapitem::tick, so they're consistent. You say...
The program only successfully compiles and runs when I add the const keyword to the tick() function. This is a problem because tick() needs to operate on some class member variables.
...so it sounds like removing it is what you want to do.
It's also a good idea to add override to Residential::tick() so the compiler's obliged to verify that it matches MapItem::tick():
void Residential::tick() [const] override
Declaring a member method results in a function declaration that takes an implicit this pointer as a first parameter.
So a method void Residential::tick() (without the const at the end) results in a function like void Residential::tick(Residential* this).
Now adding the const at the end void Residential::tick() const can then be understood as a declaration with a const this pointer:
void Residential::tick(const Residential* this)
so, when you declare void Residential::tick() const in base class and then declare void Residential::tick() in derived class, the function signatures donot match and compiler throws an error.
So, decide which signature you need(const qualified/non const) and make sure both the signatures match.
I have a problem in MSVC++ 2008 where VS2008 is throwing this compile error:
error C2509: 'render' : member function not declared in 'PlayerSpriteKasua'
Now, what's confusing me is that render() is defined, but in an inherited class.
The class definition works like this:
SpriteBase -Inherited By-> PlayerSpriteBase -Inherited By-> PlayerSpriteKasua
So, a pared-down version of SpriteBase.h is the following:
class SpriteBase {
public:
//Variables=============================================
-snip-
//Primary Functions=====================================
virtual void think()=0; //Called every frame to allow the sprite to process events and react to the player.
virtual void render(long long ScreenX, long long ScreenY)=0; //Called every frame to render the sprite.
//Various overridable and not service/event functions===
virtual void died(); //Called when the sprite is killed either externally or via SpriteBase::kill().
-snip-
//======================================================
};
PlayerSpriteBase.h is this:
class PlayerSpriteBase : public SpriteBase
{
public:
virtual void pose() = 0;
virtual void knockback(bool Direction) = 0;
virtual int getHealth() = 0;
};
And finally, PlayerSpriteKasua.h is this:
class PlayerSpriteKasua : public PlayerSpriteBase
{
public:
};
I know there are no members in it yet, but that's simply because I hadn't gotten to adding them. Same goes for PlayerSpriteBase; there's other stuff left to go in to it.
The code in PlayerSpriteKasua.cpp is this:
#include "../../../MegaJul.h" //Include all the files needed in one go
void PlayerSpriteKasua::render(long long ScreenX, long long ScreenY) {
return;
}
void PlayerSpriteKasua::think() {
return;
}
int PlayerSpriteKasua::getHealth() {
return this->Health;
}
When I type, say, void PlayerSpriteKasua::, Intellisense pops up listing all the members of PlayerSpriteBase and SpriteBase just fine, but on compile it fails like I said above.
Is there any particular reason I'm getting this error?
PlayerSpriteBase.cpp is empty and has nothing in it as of yet.
SpriteBase.cpp has plenty of function definitions for SpriteBase, and uses the same format as PlayerSpriteKasua.cpp:
void SpriteBase::died() {
return;
}
is an example.
In PlayerSpriteKasua.h you need to re-declare whatever methods you're going to override/implement (without the "=0" to say that those methods are not abstract anymore). So you need to write it like follows:
class PlayerSpriteKasua : public PlayerSpriteBase
{
public:
virtual void think();
virtual void render(long long ScreenX, long long ScreenY);
virtual int getHealth();
};
...or did you omit that to keep your post shorter?
You need to provide a declaration for PlayerSpriteKasua::render() in your class definition. Otherwise, other translation units including your PlayerSpriteKasua.h wouldn't be able to tell that you'd provided a definition, and would be forced to conclude that PlayerSpriteKasua can't be instantiated.
You need to redeclare the members of SpriteBase that you are going to implement in PlayerSpriteKasua in the declaration of PlayerSpriteKasua in PlayerSpriteKasua.h.