I'm messing up my inheritance - c++

So I've got a Piece class supposed to represent pieces on a board, from which I plan to have two other classes inheriting. I've gotten a lot of problems in doing so, however; here is the relevant code so far.
///
/// PIECE CLASS HERE
/// this is an abstract class from which Barrier and Pawn inherit.
class Piece
{
public:
Piece(Space* start);
sf::Shape m_Circle;
protected:
int m_X;
int m_Y;
int m_radius;
Space* CurrentSpace;
};
Piece::Piece(Space* start):
m_X(start->GetX()),
m_Y(start->GetY()),
m_radius(14),
CurrentSpace(start)
{}
///
/// BARRIER CLASS HERE
/// these are the white stones that block a player's path
class Barrier : public Piece
{
public:
Barrier(Space* initial);
void Move(Space* target, bool isCapturing);
};
Barrier::Barrier(Space* initial)
{
Piece(initial);
m_Circle = sf::Shape::Circle((float)m_X, (float)m_Y, (float)m_radius, sf::Color(255, 255, 255));
Move(initial);
}
void Barrier::Move(Space* target, bool isCapturing)
{
int xChange = abs(target->GetX() - m_X);
int yChange = abs(target->GetY() - m_Y);
m_Circle.Move((float)xChange, (float)yChange);
CurrentSpace.ToggleOccupied();
if(!isCapturing)
{
(*target).ToggleOccupied();
}
CurrentSpace = target;
}
I'm getting loads of errors I don't understand, in particular:
no matching function for call to Piece::Piece()
declaration of 'Piece initial' shadows a parameter
no matching function for call to 'Barrier::Move(Piece&)'
request for member 'ToggleOccupied' in '((Barrier*)this)->Barrier::<anonymous>.Piece::CurrentSpace', which is of non-class type 'Space*'|
Being new to C++, I don't understand what's going wrong with any of this. I tried to build my code analogous to the code I found in the book I used to learn C++, but apparently I've overlooked some subtlety. All the functions that I try to call seem to exist in the appropriate places, and I define them with the same values as in their prototype, I think.

The first error is caused by this:
Barrier::Barrier(Space* initial)
{
Piece(initial);
m_Circle = sf::Shape::Circle((float)m_X, (float)m_Y, (float)m_radius, sf::Color(255, 255, 255));
Move(initial);
}
Needs to look like:
Barrier::Barrier(Space* initial) : Piece(initial)
{
m_Circle = sf::Shape::Circle((float)m_X, (float)m_Y, (float)m_radius, sf::Color(255, 255, 255));
Move(initial);
}
The base class' constructor runs before your constructor (no matter what) -- you need to pass arguments to it if it requires arguments in the initialization list.
I'm not sure about the other errors because I don't know which lines they're occurring on.

The parenthesis in the line
Piece(initial);
are ignored by the compiler. You are declaring a variable with the same name as the parameter:
Piece initial;
To initialize the Piece base object with initial, you have to use the member initializer list:
Barrier::Barrier(Space* initial) : Piece(initial)
Also, the Move function expects two arguments, but you're only passing one. You forgot the boolean.

Good answers, all. Plus that final daunting line
request for member 'ToggleOccupied' in '((Barrier*)this)->Barrier::<anonymous>.Piece::CurrentSpace', which is of non-class type 'Space*'|
is being caused from
CurrentSpace.ToggleOccupied();
you have declared CurrentSpace to be a pointer, so this should be
CurrentSpace->ToggleOccupied();

If you want to initialize the super class, you should do it like this:
Barrier(Space* initial):
Piece(initial) {
...
}
If you don't explicitly initialize the base type, the compiler will try to initialize it by calling a constructor with an empty argument list, like this:
Barrier(Space* initial):
Piece() {
...
}
But since you don't define a constructor for Piece that takes zero arguments, you get the compiler error you described.

Related

Initializing a new nested class from outer class function

I'm currently learning nested classes in C++ while building a project and I currently inside setupBLE() I need to pass one of the nested classes but to init that new class I need to pass to its constructor the outer class so it can access its variables and functions but I'm not exactly sure how to pass to the constructor the pointer of the class that's trying to create it.
It's a bit confusing so I hope the code helps with it.
Like in python we have self but in C++ as far as I know we don't have that so I was wondering what should I pass to the constructor.
Code (PillDispenser.h):
class PillDispenser {
public:
explicit PillDispenser(BLEAddress deviceAddress);
private:
BLEAddress _device_address;
BLEAdvertisedDevice _device;
bool _connected;
// Device properties
std::string _device_name;
// Callbacks
static void notifyCallBack();
class AdvertisedDeviceCallBack : public BLEAdvertisedDeviceCallbacks {
PillDispenser &_outer;
explicit AdvertisedDeviceCallBack(PillDispenser &outer) : _outer(outer){};
void onResult(BLEAdvertisedDevice advertisedDevice) override;
};
}
Code (PillDispenser.cpp):
void PillDispenser::setupBLE() {
BLEScan *scanner = BLEDevice::getScan();
scanner->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallBack());
scanner->setInterval(SCAN_INTERVAL);
scanner->setWindow(SCAN_WINDOW);
scanner->setActiveScan(true);
scanner->start(SCAN_DURATION);
}
Issue:
This line is trying to use the default constructor which does not exist
scanner->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallBack());
instead you should use the explicit constructor you defined
scanner->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallBack(*this));
note that this (in this context) has type PillDispenser* so you have to dereference with * to get a PillDispenser&

no matching function for call to 'WidgetBridge::WidgetBridge()'

I've visited this forum many many many times, but this is my actual first post here. Usually I can find my answer here and I guess I've probably found it this time, but this time my knowledge is lacking to understand the solutions given (been learning C++ for the last 2 weeks).
The error I get:
no matching function for call to 'WidgetBridge::WidgetBridge()'
an extraction of my (rather lengthy) code:
class Room {
private:
//initializer list of internal objects
WidgetBridge bridge_thermostat;
WidgetBridge bridge_relay;
public:
//Constructor of the class:
Room() : bridge_thermostat(V100), bridge_relay(V107){}
void initBridges(String authThermostat, String authRelay){
bridge_thermostat.setAuthToken(authThermostat);
bridge_relay.setAuthToken(authRelay);
}
void receiveCurrentT(float param){
currentT = param;
Blynk.virtualWrite(V10, currentT);
timer.restartTimer(thermostatTimer ); //reset isDead timer for thermostat
Blynk.setProperty(V17, "color", BLYNK_GREEN); //change LED color
Blynk.virtualWrite(V17, 200);
}
} livingRoom;
BLYNK_CONNECTED() {
Blynk.syncAll();
livingRoom.initBridges("xxx", "xxxx"); //auth of: thermostat, relay
}
BLYNK_WRITE(V10){ livingRoom.receiveCurrentT(param.asFloat()); } //receive currentT from thermostat
Based on the answers I've found on this forum it appears that WidgetBridge doens't have its own constructor when called. Based on the answers given I've also tried:
public:
//Constructor of the class:
Room() : {
bridge_thermostat = V100;
bridge_relay = V107;
}
but that rendered the same error. I've continued reading about static fields, constructors, namespaces, etc. but bottomline: I'm stuck and I don't know how to fix this.
Additional info: code is for an esp8266 arduino wifi module which communicates with other esp8266's (relay and thermostat). The communication takes place through 'bridges' which are created using code from the Blynk app.
Thank you for your time!
UPDATE: I've finally found the actual calss widgetbridge itself. And from the mentioned solution I gathered that it has no constructor of itself, but it does..so now I'm really lost. Here's part of the widget class:
class WidgetBridge
: private BlynkWidgetBase
{
public:
WidgetBridge(uint8_t vPin)
: BlynkWidgetBase(vPin)
{}
void setAuthToken(const char* token) {
char mem[BLYNK_MAX_SENDBYTES];
BlynkParam cmd(mem, 0, sizeof(mem));
cmd.add(mPin);
cmd.add("i");
cmd.add(token);
Blynk.sendCmd(BLYNK_CMD_BRIDGE, 0, cmd.getBuffer(), cmd.getLength()-1);
}
(....)
};
From the code extract you posted (partial) and the error message(partial too...) , the only reasonable answer is that the WidgetBridge class as no default constructor (i.e. constructor with 0 argument).
Probably because the base class BlynkWidgetBase has no default constructor as well.
So you get compiler errors on those lines
//initializer list of internal objects
WidgetBridge bridge_thermostat;
WidgetBridge bridge_relay;
You can either implement a WidgetBride default constructor or instanciate those two variables with the constructor taking a uint8_t parameter :
//initializer list of internal objects
WidgetBridge bridge_thermostat(3);
WidgetBridge bridge_relay(4);
3 and 4 to be replaced by whatever value that makes sense, but only you can know that from the code extract

What does minDist(100) and the curly braces in this piece of code mean?

I've just met a piece of code that made me confused. It's a header file that defines a class named ColorDetector. The private part is as follows:
class ColorDetector {
private:
// minimum acceptable distance
int minDist;
// target color
cv::Vec3b target;
// image containing resulting binary map
cv::Mat result;
// inline private member function
// Computes the distance from target color.
int getDistance(const cv::Vec3b& color) const {
// return static_cast<int>(cv::norm<int,3>(cv::Vec3i(color[0]-target[0],color[1]-target[1],color[2]-target[2])));
return abs(color[0]-target[0])+
abs(color[1]-target[1])+
abs(color[2]-target[2]);
}
Here's the public declaration of this class that made me confused:
public:
// empty constructor
ColorDetector() : minDist(100) {
// default parameter initialization here
target[0]= target[1]= target[2]= 0;
}
I am not quite clear about the grammar in this constructor here. What does mindset(100) mean here and why the target array is written within curly braces? I searched google with keyword "default constructor" and "default parameter" but found no relating articles. Can someone tell me the exact meaning of this piece of code here?
The class of this
This is member initialization list see http://en.cppreference.com/w/cpp/language/initializer_list

Call virtual function from another subclass

I've been set an assignment to create an rpn calculator that takes infix notation as input. So part of it is that it has to print out different stages of the process. So first it should separate a string into tokens and then store in a vector. Then it should convert this to rpn notation (e.g 3+4 -> 3 4 +) which is the part im stuck on now the part I'm stuck on now.
I've been recommended to use virtual abstract functions for this. So first I create a class with the abstract function. Then I create a subclass which converts a string to tokens stored in a string vector, this part works fine. Then I should create another subclass which converts the input string to rpn notation, therefore I have to call the function to convert to tokens at the start of this sub-class, this is the bit which I think is going wrong.
I have been given some code as a template and so far it's been very buggy so there might be something wrong with the syntax where the error is.
So I have this as my main class
template<typename T>
class tokenstream {
public:
virtual bool process(const std::string& input, std::vector<T>& output) = 0;
};
Then this as the first subclass
class tokenifier: public tokenstream<std::string> {
public:
bool process(const std::string& input, std::vector<std::string>& output) {
//this part works fine, ive tested it.
};
So then I have to create another subclass and then call the above function inside it, this is the part where it goes wrong.
class infix2rpn: public tokenstream<std::string> {
private:
tokenifier *tokens;
public:
tokenifier(tokenstream *_tokens): tokens(_tokens) {} //I think this line is the problem
bool process(const std::string& input, std::vector<std::string>& output) {
//call the underlying tokenstream object
std::vector<std::string> infixtokens;
if(!tokens->process(input, infixtokens))
{
return false;
}
return shunting_yard(infixtokens, output);
}
bool shunting_yard(const std::vector<std::string>& input, std::vector<std::string>& output){
//i've tested the shunting_yard algorithm and it works fine
}
};
When I try to compile it I get the error "ISO C++ forbids declaration of 'tokenifier' with no type [-fpermissive].
So the part I don't understand is how to call other virtual functions from another subclass.
Thanks
Your class is called infix2rpn, so its constructor should be named infix2rpn as well, not tokenifier. This has nothing to do with virtual functions.
Moreover, your attribute should be a tokenstream<std::string>*, not a tokenifier*, because you can't convert the tokenstream<std::string>* you get in the constructor to a tokenifier*.
tokenifier(tokenstream *_tokens): tokens(_tokens) {}
This was probably meant to be constructor, but in that case, the name of the method should be infix2rpn, same as the class name.
The error means, that you specified method tokenifier that has not specified return type, only constructors and destructors have no return type.
Note that void also specification of return type, in that case it means nothing returned.

What's wrong with this constructor?

class Ball
{
public:
int i,j,iplus,jplus;
Ball(int i , int j , int iplus , int jplus)
{ iplus=1;
jplus=1;
i=400;
j=300;
}
};
int main()
{
Ball toop(Ball);
}
I get the following error:
request for member ‘jplus’ in ‘toop’, which is of non-class type ‘Ball(Ball)’
Ball toop(Ball);
should be something like:
Ball toop(10,20,30,40);
Accidentally(as most users), you have created is called as the Most Vexing Parse in C++.
It does not create a object as you think it does, instead it declares a function which takes Ball as an input parameter and returns Ball.
Ball toop(Ball); //function declaration
It declares a function toop which takes one argument of type Ball, and returns Ball. It doesn't define an object.
I think you wanted to write something like this:
Ball toop(1,2,3,4); //object definition
Apart from that you should be using member-initialization-list in the constructor as:
Ball(int i , int j , int iplus , int jplus)
: i(i), j(j), iplus(iplus), jplus(jplus)
{ //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ its called member-initialization-list
}
Here, the syntax i(i) looks weird, but it means the other outer i is initialized with the inner i. The inner i is the constructor parameter-name, and the outer i is the member of the class, as shown below:
: i (i), j(j), iplus(iplus), jplus(jplus)
^ ^
| parameter-name
class-member-name
Similar explanation is for others as well : j(j), iplus(iplus), jplus(jplus)
Ball toop(Ball);
declares a function.
You didn't show the rest of your code, but it says
toop.jplus
somewhere else. That doesn't fly, because toop is a function pointer (non-class type). A function type doesn't support the member access operator (.) hence the error message.
Ball toop(1,2,3,4);
int y = toop.jplus;
would work. Although I'm mighty interested what you are trying to achieve in the constructor :)
I suggest:
class Ball
{
public:
int i,j,iplus,jplus;
Ball() : jplus(1), iplus(1), i(400), j(300)
{
}
};
int main()
{
Ball toop; // **not** toop()!
int test = toop.j; // 300
}
You forgot to post your full testcase. The code you posted is perfectly valid.
What your main presumably really looks like is:
int main() {
Ball toop(Ball);
toop.jplus = 2; // or something
}
Except when you tried to create toop, you actually just declared a function called toop that takes and returns objects of type Ball. I'm not quite sure why you've done that.
To use your constructor and create an object, use code that looks like this:
Ball toop(1,2,3,4);
And please, next time, post an actual testcase that reproduces the problem. You were lucky that:
the error message gave the issue away
I'm very good
Ball toop(Ball);
is wrong because you declared it with 4 parameters, so you should pass the four parameters. Like Your constructor is taking 4 integers as parameter so pass 4 integer values
Like
Ball toop(0,0,0,0);
Or
int x=0;
Ball toop(x,x,x,x);