I want to count ascending and descending data for each created object.But I can't handle it separately because the 2 objects I created also use the same static variable.The codes are as follows, How do I have to make changes.
void MyObject::handle_receive(std::size_t length) {
getIncrementCount()++;
if(some-condition)
{
getIncrementCount() = 0;
getDecreaseCount() = 0;
}
}
void MyObject::handle_timeout() {
getDecreaseCount()++;
if(some-condition)
{
getIncrementCount() = 0;
getDecreaseCount() = 0;
}
}
int & MyObject::getDecreaseCount()
{
static int theCount = 0;
return theCount;
}
int & MyObject::getIncrementCount()
{
static int theCount = 0;
return theCount;
}
main()
{
for (size_t i = 0; i < SensorSettingsList.size(); i++) {
try {
MyObject *ipPingReporter = new MyObject(io_service, SensorSettingsList.at(i).biosName);
}
catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
}
}
Please revisit the meaning of static. It is exactly the opposite of what you want - it is a variable that is shared between all objects of the same type.
For keeping state in an object, you need to make the variable part of the class, not of the function:
class MyObject {
int incrementCount;
void increment() {
++incrementCount;
}
int getIncrementCount() {
return incrementCount;
}
};
(I implemented the methods within the class for brevity. You can continue to implement them in void MyObject::increment, which is arguably better.)
Other than that (somewhat unrelated to your question), I would suggest that you do not return references to those variables. You do not want an outside class to modify the value. Right now, in your code, there is nothing that keeps me from messing up the counts by calling someObject.getIncrementCount() = 15.
Related
I'm trying to create a Monopoly game in C++ and I've been messing with object-oriented-programming, the problem happens with the classes "Game" and "Player", I would like to know how to use "Game"'s functions inside "Player" and "Player"'s functions inside "Game", but I've been getting a compiler error saying that the class is not defined.
Switching class positions won't work (obviously) but I tried anyways.
Code (reduced and minimized to the Game and Player classes):
namespace Monopoly {
typedef enum { normal, train, company, incometax, luxurytax, start, chancecard, chestcard, jail } type;
class Game {
private:
bool running = false;
int turn = 1;
int currentPlayerID;
int startingMoney = 1000;
std::vector<Player> players;
public:
// Functions
void createPlayer() {
++currentPlayerID;
Player newPlayer(currentPlayerID, startingMoney);
players.push_back(newPlayer);
++currentPlayerID;
}
void createPlayers(int playerAmount) {
for (int i = 0; i <= playerAmount; ++i) {
createPlayer();
}
}
Player getPlayer(int index) {
Player p = players[index];
return p;
}
};
class Player {
private:
int playerID;
int money;
std::vector<int> propertiesOwned;
void addProperty(int id) {
this->propertiesOwned.push_back(id);
}
public:
// Constructor
Player(int pID, int sMoney) {
this->playerID = pID;
this->money = sMoney;
}
// Functions
Player payMoney(int payAmount, unsigned int destinationID, Game engine) {
this->money -= payAmount;
if (destinationID > 0) {
// Checks if you're paying to a player or bank
bool playerFound = false;
for (int i = 0; i <= engine.getPlayerAmount(); ++i) {
if (engine.getPlayer(i).getID() == destinationID) {
playerFound = true;
break;
}
}
if (playerFound) {
// Player was found
engine.getPlayer(destinationID).giveMoney(payAmount);
return;
}
else {
std::cout << "\nERROR: Invalid player ID at function payMoney\n";
return;
}
}
else {
// You're paying to the bank
}
return;
}
void buyProperty(int id, int price, Game engine) {
payMoney(price, 0, engine);
addProperty(id);
}
void giveMoney(int payMoney) {
this->money += payMoney;
}
// Returns
inline int getMoney() { return this->money; }
inline int getID() { return this->playerID; }
inline auto getProperties(int index) {
auto p = propertiesOwned[index];
return p;
}
inline int getPropertyAmount() {
int amount = std::size(propertiesOwned);
return amount;
}
};
}
I expected the classes to run the other classes function normally, but it seens like that in C++, classes are defined in certain order, and you can only access classes (in a class) declared before the class you're using, feedback and alternatives that fix this would help
You are correct that in C++ declaration order matters, and that is the cause of your errors, however there are a few other issues with the code.
Firstly, you should swap the order that Game and Player are defined. This will make it easier, as Player relies on Game fewer times than Game relies on Player.
Next, add a forward declaration for Game before the definition of Player:
class Game;
This tells the compiler that a class named Game exists and allows you to use it in scenarios where it doesn't need to know the contents (i.e. definition) of the class.
Next, make payMoney and buyProperty accept their engine parameter by reference instead of by value by changing the parameter specifier to Game &engine. This is important for two reasons. First, passing by value can only be done if you have already defined the type, which we have not (we've only declared it). Second, passing by value creates a copy of the object, which in this case means a completely new vector of completely new Player objects, and the changes will not synchronize back to the old object. See here for a better explanation of references.
Next, you need to extract the definition of payMoney to after the definition of Game. The reason is that while the parameter list of payMoney no longer relies on the definition of Game, the code in the function body does (because it calls functions on the engine object). See the end for what this looks like.
This fixes all the problems with declaration/definition order. You also should make payMoney return void as its return value is never provided and never used, pick a consistent type for IDs (either int or unsigned int, not a mix), and add the getPlayerAmount to Game.
Here's what the final code could look like:
namespace Monopoly {
typedef enum { normal, train, company, incometax, luxurytax, start, chancecard, chestcard, jail } type;
class Game;
class Player {
private:
int playerID;
int money;
std::vector<int> propertiesOwned;
void addProperty(int id) {
this->propertiesOwned.push_back(id);
}
public:
// Constructor
Player(int pID, int sMoney) {
this->playerID = pID;
this->money = sMoney;
}
// Functions
void payMoney(int payAmount, int destinationID, Game &engine);
void buyProperty(int id, int price, Game &engine) {
payMoney(price, 0, engine);
addProperty(id);
}
void giveMoney(int payMoney) {
this->money += payMoney;
}
// Returns
inline int getMoney() { return this->money; }
inline int getID() { return this->playerID; }
inline auto getProperties(int index) {
auto p = propertiesOwned[index];
return p;
}
inline int getPropertyAmount() {
int amount = std::size(propertiesOwned);
return amount;
}
};
class Game {
private:
bool running = false;
int turn = 1;
int currentPlayerID;
int startingMoney = 1000;
std::vector<Player> players;
public:
// Functions
void createPlayer() {
++currentPlayerID;
Player newPlayer(currentPlayerID, startingMoney);
players.push_back(newPlayer);
++currentPlayerID;
}
void createPlayers(int playerAmount) {
for (int i = 0; i <= playerAmount; ++i) {
createPlayer();
}
}
Player getPlayer(int index) {
Player p = players[index];
return p;
}
int getPlayerAmount() {
int amount = players.size();
return amount;
}
};
void Player::payMoney(int payAmount, int destinationID, Game &engine) {
this->money -= payAmount;
if (destinationID > 0) {
// Checks if you're paying to a player or bank
bool playerFound = false;
for (int i = 0; i <= engine.getPlayerAmount(); ++i) {
if (engine.getPlayer(i).getID() == destinationID) {
playerFound = true;
break;
}
}
if (playerFound) {
// Player was found
engine.getPlayer(destinationID).giveMoney(payAmount);
return;
}
else {
std::cout << "\nERROR: Invalid player ID at function payMoney\n";
return;
}
}
else {
// You're paying to the bank
}
return;
}
}
Side note: it's technically better C++ to use size_t instead of int for variables storing the size of vectors, as that is what the size functions return (and it's an unsigned integer type whereas int is signed), but that's not especially important.
I'd like to have 2 different Data instances used in the client without either changing the static key in its member or resetting its member's value.
struct Data
{
static std::vector<int> vi;
};
struct DataUser
{
DataUser(int s) {
for (int i = 0; i < s; ++i)
{
Data::vi.emplace_back(i);
}
}
int getSize() { return Data::vi.size(); }
};
std::vector<int> Data::vi(0);
//.............. use it
int main()
{
{
DataUser d1(5);
std::cout << d1.getSize() << "\n";
}
{
DataUser d2(10);
std::cout << d2.getSize() << "\n";
}
}
e.g the output of the program is
5
15
I'd like it to be
5
10
static always means there is only one single instance of it in one binary.
The only way to have separate instances is to have a Data member and non static member in Data.
I am having trouble in initializing an array of structures with a function pointer as a member in it.
class Record
{
private:
typedef void (*display_fn_t) ();
struct record {
int a;
display_fn_t disp;
};
static const record rec[];
void disp1() { cout << "Display 1 with a string to display" << endl; }
void disp2() { cout << "Display 2 with an integer to display" << endl; }
public:
int find() { /* logic to find the record comes here */ }
void display() {
for (int i = 0; i < 2; i++) {
rec[i].disp();
}
}
}
const Record::record Record::rec[] = {
{ 10, disp1 },
{ 11, disp2 }
};
int main()
{
Record r;
if (r.find())
r.display();
return 0;
}
When I compile the above code, I am getting the following compilation error:
mca_record.cpp:56: error: argument of type ‘void (Record::)()’ does
not match ‘void (*)()’
Your syntax is wrong and isn't using the appropriate operators.
Fixing a multitude of syntax errors, and stripping out the unrelated find operation, then utilizing proper member function pointers and operator ->* gives the following (one of several ways to do this):
#include <iostream>
class Record
{
private:
typedef void (Record::*display_memfn_t)();
struct record
{
int a;
display_memfn_t disp;
};
static const record rec[];
void disp1() { std::cout << "Display 1 with a string to display" << std::endl; }
void disp2() { std::cout << "Display 2 with an integer to display" << std::endl; }
public:
void display();
};
const Record::record Record::rec[] =
{
{ 10, &Record::disp1 },
{ 11, &Record::disp2 }
};
void Record::display()
{
for (size_t i=0; i<sizeof rec/sizeof*rec; ++i)
(this->*(rec[i].disp))();
}
int main()
{
Record r;
r.display();
return 0;
}
Output
Display 1 with a string to display
Display 2 with an integer to display
Compare it to your existing code, and not in particular that pointers to member functions are not simply pointers to functions. They require different handling and generally different operators to utilize. See here for different methods of member access (both variable and function).
Best of luck.
To make the call work you must invoke it like this:
for (int i = 0; i < 2; i++) {
(*rec[i].disp)();
}
And initialize the table this way:
const Record::record Record::rec[] = {
{ 10, &Record::disp1 },
{ 11, &Record::disp2 }
};
my type aButton has a function pointer so i can define custom actions for each button, i though the easiest way to do this would be to create a lambda and dereference it and pass it to the function pointer of that aButton instance, since i need non-static access to objects outside of the scope of the button class
but i'm stuck trying to figure out how to cast it to the right type and how to call it without getting the errors below... i haven't see many people have luck with this, and using functional doesn't look like i can pass in context???
// Example program
#include <iostream>
#include <string>
int global1 = 0;
int global2 = 5;
class aButton {
public:
int status, oldStatus;
aButton(int initStatus) { oldStatus = status = initStatus; }
int (aButton::*action)();
};
class Thingy {
private:
int mode = 1;
int value = 0;
public:
void reset() { value = 0; }
void setMode(int newMode) { mode = newMode; }
void increment() { value = value + global2; }
//accessors & mutators
};
void specialFunction(Thingy *thingyToWorkOn) {
//do stuff...
}
void anotherSpecialFunction(Thingy *firstThingy, Thingy *secondThingy) {
//more stuff...
}
int main() {
Thingy one;
Thingy two;
aButton *on = new aButton(0);
aButton *speedUp = new aButton(0);
on->action = &( //error: taking address of temporary [-fpermissive]
[&]() { //error: cannot convert 'main()::<lambda()>*' to 'int (aButton::*)()' in assignment
//some specific stuff....
global1 = 1;
if (global2 < 10) {
global2++;
}
one.reset();
two.reset();
anotherSpecialFunction(&one, &two);
std::cout << "on action \n";
return 1;
}
);
speedUp->action = &( //error: taking address of temporary [-fpermissive]
[&]() { //error: cannot convert 'main()::<lambda()>*' to 'int (aButton::*)()' in assignment
//some specific stuff....
if (global1) {
one.setMode(global2);
two.setMode(global2);
specialFunction(&one);
specialFunction(&two);
std::cout << "speedUp action \n";
return 1;
}
return 0;
}
);
for(int i=0; i<5; i++) {
//if on pushed
(on->(on->action))(); //error: expected unqualified-id before '(
//if speedUp pushed
(speedUp->(speedUp->action))(); //error: expected unqualified-id before '(
}
}
I believe that you want aButton::action to be of type std::function<int()> (read: function that takes nothing and returns int) rather than int (aButton::*). This requires the <functional> header. With that change, your assignments could stay the same (minus the leading address-of operator), though as you figured out, you'll need to explicitly state the return type with -> int. The calls would simply take the form (e.g.):
on->action();
One other note: be very careful about capturing local variables (one, two) by reference. If the function really is main then I suppose it's ok since main won't return until the program ends, but otherwise it would be asking for trouble.
You cannot assign pointer to lambda to pointer to member function. Pointers to member functions may point only to member functions.
You can indeed use std::function from <functional> instead. Declare your action as
std::function<int()> action;
so instead of using member functions you will use global functions. Of course you need to get rid of & operators for lambdas. And you need to modify the way of calling action.
Thanks guys, i guess functional was what i was looking for after all... this seems to do what i want on http://cpp.sh/8ll i guess i just got confused cause a lot of the functional examples had them as arguments for callbacks instead
// Example program
#include <iostream>
#include <string>
#include <functional>
int global1 = 0;
int global2 = 5;
class aButton {
public:
int status, oldStatus;
aButton(int initStatus) { oldStatus = status = initStatus; }
std::function<int()> action;
};
class Thingy {
private:
int mode = 1;
int value = 0;
public:
void reset() { value = 0; }
void setMode(int newMode) { mode = newMode; }
void increment() { value = value + global2; }
//...
};
void specialFunction(Thingy *thingyToWorkOn) {
//do stuff...
}
void anotherSpecialFunction(Thingy *firstThingy, Thingy *secondThingy) {
//more stuff...
}
int main() {
Thingy one;
Thingy two;
aButton *on = new aButton(0);
aButton *speedUp = new aButton(0);
on->action = std::function<int()>(
[&]() -> int{
//some specific stuff....
global1 = 1;
if (global2 < 10) {
global2++;
}
one.reset();
two.reset();
anotherSpecialFunction(&one, &two);
std::cout << "on action \n";
return 1;
}
);
speedUp->action = std::function<int()>(
[&]() -> int{
//some specific stuff....
if (global1) {
one.setMode(global2);
two.setMode(global2);
specialFunction(&one);
specialFunction(&two);
std::cout << "speedUp action \n";
return 1;
}
return 0;
}
);
for(int i=0; i<5; i++) {
//if on pushed
on->action();
//if speedUp pushed
speedUp->action();
}
}
The first time the function is called it returns 1. Every other time it's called it returns 1+the number returned the last time it was called.
int counter()
{
return counter()++;
}
Is this valid?
Sounds like you want a static variable:
int counter()
{
static int count = 0; // initialized only once across all calls
return ++count;
}
You can use static.
int counter()
{
static int counter = 0;
return ++counter;
}
Static (in the function body context) is just a nice keyword that makes a variable essentially global, but not semantic-wise. So you cannot use it outside of the function, but it gets initialized with all the globals (it means once near the start point) and it is stored where other global variables are.
Just for the record, since c++ label. You could write a functor class, with a private count variable and overload operator(). Or even probably a template that would be able to wrap any function and count its calls.
Also note that in your try, you call counter recursively with no exit point with a fixed value. It will never finish (unless you count stack overflowing as end).
Apart from defining a static local variable in the function as it was already shown you can define a static class member function that will increment a static data member of the same class. For example
#include <iostream>
class Counter
{
public:
static int Count() { return ( ++cnt ); }
static int Reset() { return ( cnt = 0 ); }
private:
static int cnt;
};
int Counter::cnt = 0;
int main()
{
for ( int i = 0; i < 10; i++ ) std::cout << Counter::Count() << ' ';
std::cout << std::endl;
std::cout << "\nResetting the counter to " << Counter::Reset() << std::endl;
for ( int i = 0; i < 10; i++ ) std::cout << Counter::Count() << ' ';
std::cout << std::endl;
}
If using C++11, use a std::function and a mutable lambda expression:
#include <iostream>
#include <functional>
using namespace std;
int main()
{
function<int()> func = [&]()
{
static int i = 1;
return i++;
};
for(int i = 0; i < 10; i++)
cout << func() << endl;
return 0;
}