I have the following code:
Card.h:
#include <string>
using namespace std;
class Card
{
public:
Card(string name);
~Card() {};
string GetName();
private:
string Name;
};
Card.cpp:
#include "Card.h"
using namespace std;
Card::Card(string name) {Name=name;};
string Card::GetName() {return Name;}
Deck.h:
#include "Card.h"
#include <vector>
class Deck {
public:
Card& DrawCard();
void AddCardToDeck(Card& c);
Deck();
~Deck();
private:
std::vector <Card> cardsindeck;
};
Deck.cpp:
#include "Deck.h"
#include <vector>
#include <iostream>
using namespace std;
Card& Deck::DrawCard() {
//cout << cardsindeck.back().GetName()<<" was drawn "<<endl;
Card &c = cardsindeck.back();
cout << c.GetName()<<" was drawn "<<endl;
cardsindeck.pop_back();
cout << c.GetName()<<" popped from deck "<<endl;
return c;
}
Deck::Deck()
{
}
Deck::~Deck()
{
}
void Deck::AddCardToDeck(Card& c) {
cardsindeck.push_back(c);
}
Player.h:
#include "Deck.h"
#include <vector>
using namespace std;
class Player {
public:
void Beginning();
Player(Deck _deck);
~Player() {};
private:
vector <Card> cardsindeck;
Deck deck;
};
Player.cpp:
#include "Player.h"
using namespace std;
Player::Player(Deck _deck)
{
this->deck = _deck;
}
void Player::Beginning()
{
Card& c = deck.DrawCard();
}
main.cpp:
#include "Player.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
Deck aDeck;
vector <Card> aHand;
Card c=Card("THIS THIS GREAT PLAYER");
Card& c1 =c;
aDeck.AddCardToDeck(c1);
Player P = Player(aDeck);
P.Beginning();
return 0;
}
The output I get is:
THIS THIS GREAT PLAYER was drawn
�\IS GREAT PLAYER popped from deck
Why does the 2nd line have that weird chars in place of "THIS THIS" ?
You have undefined behavior in this function:
Card& Deck::DrawCard() {
// ...
Card &c = cardsindeck.back();
// ...
cardsindeck.pop_back();
cout << c.GetName()<<" popped from deck "<<endl;
return c;
}
First, you alias the last element of cardsindeck with a reference called c. This is fine, and access to its member function is fine, too. Then, you remove the element from the container with cardsindeck.pop_back();. From the docs on std::vector::pop_back, we see that
No iterators or references except for back() and end() are invalidated.
And that's the issue here. You are having a reference to back(), and that is invalidated. It must be - you are deleting the element in the vector that c refers to from the container. Accessing its members then e.g. by GetName() is UB, then.
You can easily fix the issue by copying the return value of cardsindeck.back() like this:
Card c = cardsindeck.back();
// ^^ No reference. The last element is copied
cardsindeck.pop_back(); // Doens't affect the copied instance above
return c;
Note that this requires changing the signature of the member function to
Card Deck::DrawCard()
where the return value is no reference anymore.
Related
I'm having this issue on another program, but I tried to simplify it with this one. I cannot set the weapon name through p.getWeaopn().setName("sword"); It works fine when I simply set it through its own object, but when I try to access the setter through player it doesn't set anything.
#include <iostream>
#include <string>
#include "Player.h"
#include "Weapon.h"
using namespace std;
int main()
{
Player p; // Player contains only a Weapon weapon;
Weapon w; // Weapon only contains a string name;
//w.setName("sword"); // this changes the name of the weapon
p.setWeapon(w);
p.weapon.setName("sword"); // this also changes the name
p.getWeapon().setName("sword"); // this is not setting the name. Why?
// checking if weapon has a name
if (p.getWeapon().getName().empty())
{
cout << "Weapon name is empty!" << endl;
}
else
{
cout << "Weapon name is " << p.getWeapon().getName() << endl;
}
}
Weapon.h
#pragma once
#include <string>
using namespace std;
class Weapon
{
private:
string name;
public:
string getName();
void setName(string);
};
Weapon.cpp
#include "Weapon.h"
string Weapon::getName()
{
return name;
}
void Weapon::setName(string n)
{
name = n;
}
Player.h
#pragma once
#include "Weapon.h"
class Player
{
private:
Weapon weapon;
public:
Weapon getWeapon();
void setWeapon(Weapon);
};
Player.cpp
#include "Player.h"
Weapon Player::getWeapon()
{
return weapon;
}
void Player::setWeapon(Weapon w)
{
weapon = w;
}
Weapon Player::getWeapon()
You return a copy and not a reference of the weapon, so any change to the copy does not affect the original.
For return a reference, use & operator:
Weapon& Player::getWeapon()
{
return this->weapon;
}
Player::getWeapon() returns a copy of the weapon every time instead of a reference to the weapon. Changing the name in the copy changes nothing in the original.
I have a C++ project in Visual Studio 2015.
GameManager.h and Input.h both give me a syntax error: identifier 'Player'. This happens because I want to give an object of type 'Player' as an argument to functions in these two Header files and their appropriate C++ Files.
How do I fix that? For further information I have provided my code.
main.cpp:
#include "GameManager.h"
#include "Input.h"
#include "Player"
#include <iostream>
#include <string>
using namespace std;
const int maxPlayerCnt = 10;
static Player p1, p2, morePlayers[maxPlayerCnt];
int main()
{
GameManager game;
game.Game(p1, p2, morePlayers);
return 0;
}
It creates an object of type GameManager and 3 objects of type Player.
GameManager.h:
#include "Player.h"
class GameManager
{
public:
void Game(Player p1, Player p2, Player morePlayers[]);
};
GameManager.cpp:
#include "GameManager.h"
void GameManager::Game(Player p1, Player p2, Player morePlayers[])
{
int playerCnt = 0;
Input input;
input.getPlayerDetails(playerCnt, p2);
input.getMorePlayerDetails(playerCnt, morePlayers);
}
It creates an object of type Input to use further functions and will get more code, once I figure this problem out. And then calls to functions with specific arguments it gets from main.cpp
Input.h:
#pragma once
#include "Player.h"
#include <iostream>
#include <string>
using namespace std;
class Input
{
public:
Input();
void getPlayerDetails(int &playerNum, Player p);
void getMorePlayerDetails(int &playerNum, Player p[]);
};
It includes everything Input.cpp needs and initializes the funcitons
Input.cpp:
#include "Input.h"
void Input::getPlayerDetails(int &playerNum, Player p)
{
playerNum++;
string currentName;
char currentSymbol;
cout << "Player " << playerNum << ", what is your name?\n";
cin >> currentName;
p.setName(currentName);
cout << currentName << " what is your symbol?\n";
cin >> currentSymbol;
p.setSymbol(currentSymbol);
}
void Input::getMorePlayerDetails(int &playerNum, Player p[])
{
int plNum = playerNum;
if (playerNum >= 12)
cout << "You can't get another player!\n";
else
{
//getPlayerDetails(p[playerNum - 2], (plNum - 2));
}
}
It for now has all the functions needed and both get an object of type Player. And the second function is not quite done now. But that is not important.
Player.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Player
{
private:
string _name;
char _symbol;
public:
Player();
void getName();
void setName(string name);
void setSymbol(char symbol);
};
Player.cpp:
#include "Player.h"
Player::Player()
{
}
void Player::getName()
{
cout << "I have no name!\n";
}
void Player::setName(string name)
{
_name = name;
}
void Player::setSymbol(char symbol)
{
_symbol = symbol;
}
If you can help me, I would be pleased to see your response.
I am attempting to make part of a program that uses a bank account class as the base class and checking and savings as the derived classes. I have been trying to set up the basic framework before I do any fancy data handling and I've followed some tutorials to get a better understanding of classes and inheritance.
I have looked for answers but the answers I have found don't seem to be my problem but I might just need another set of eyes on my code.
the compiler errors:
In function main':
badriver.cpp:20: undefined reference toChecking::getAccount()'
badriver.cpp:23: undefined reference to Checking::setAccount(int)'
badriver.cpp:24: undefined reference toSavings::setAccount(int)'
badriver.cpp:26: undefined reference to `Checking::getAccount()'
badriver.cpp
#include "BankAccount.cpp"
#include "Checking.cpp"
#include "Savings.cpp"
#include <string>
#include <iostream>
using namespace std;
int main(){
Checking c;
Savings s;
cout << "Checking: " << c.getAccount() << " - Type: " << c.getType() << endl;
cout << "Savings: " << s.getAccount() << " - Type: " << s.getType() << endl;
c.setAccount(9);
s.setAccount(15);
cout << "New Checking: " << c.getAccount() << endl;
cout << "New Savings: " << s.getAccount() << endl;
return 0;
}
BankAccount.h
#ifndef BANKACCOUNT_H
#define BANKACCOUNT_H
#include <string>
using std::string;
using std::ostream;
using std::istream;
class BankAccount{
private:
int myAccount;
const char* color;
public:
// default constructor
BankAccount();
BankAccount(int account);
virtual ~BankAccount();
virtual void setAccount(int)=0;
int getAccount();
//
// void setSAccount(int);
// int getSAccount();
//
virtual const char* getColor();
virtual const char* getType() = 0;
//virtual const char* getCType() = 0;
protected:
void setColor(const char*);
};
#endif // BANKACCOUNT_H
BankAccount.cpp
#include "BankAccount.h"
#include "Checking.h"
#include "Savings.h"
#include <string>
#include <iostream>
#include <cstdlib>
using namespace std;
// default constructor
BankAccount::BankAccount(){
account = 1;
}
BankAccount::~BankAccount(){}
// void BankAccount::setAccount(int account){
// myAccount = account;
// }
int BankAccount::getAccount(){
return myAccount ;
}
BankAccount::BankAccount(int account){
myAccount = account;
}
const char* BankAccount::getColor(){
return color;
}
void BankAccount::setColor(const char* c){
color = c;
}
Checking.h
#ifndef CHECKING_H
#define CHECKING_H
#include "BankAccount.h"
#include <string>
using std::string;
using std::ostream;
using std::istream;
class Checking : public BankAccount{
private:
const char* type;
public:
Checking();
virtual ~Checking();
void setAccount(int account);
virtual const char* getType();
void setChecking(int);
int getChecking();
};
#endif //CHECKING_H
Checking.cpp
#include "Checking.h"
#include <string>
#include <string>
#include <iostream>
#include <cstdlib>
using namespace std;
Checking::Checking() : BankAccount(1), type("Checking"){}
Checking::~Checking(){}
BankAccount::~BankAccount(){}
void BankAccount::setAccount(int account){
myAccount = account;
}
const char* Checking::getType(){
return type;
}
Savings.h
#ifndef SAVINGS_H
#define SAVINGS_H
#include "BankAccount.h"
#include <string>
using std::string;
using std::ostream;
using std::istream;
class Savings: public BankAccount{
private:
const char* type;
public:
Savings();
virtual ~Savings();
void setAccount(int account);
virtual const char* getType();
void setSavings(int);
int getSavings();
};
#endif // SAVINGS_H
Savings.cpp
#include "Savings.h"
#include <string>
#include <string>
#include <iostream>
#include <cstdlib>
using namespace std;
Savings::Savings() : BankAccount(2), type("Savings"){}
Savings::~Savings(){}
BankAccount::~BankAccount(){}
void BankAccount::setAccount(int account){
myAccount = account;
}
const char* Savings::getType(){
return type;
}
Thanks for any help pointing me in the right direction.
Checking.cpp and Savings.cpp contain:
BankAccount::~BankAccount(){}
void BankAccount::setAccount(int account){
myAccount = account;
}
This causes undefined behaviour because you defined those functions in multiple files. You need to delete those lines from Checking.cpp and Savings.cpp, and instead put in definitions for the functions which are listed as being missing in the compiler output:
void Checking::setAccount(int account){
// code here
}
etc.
So here is the main where i'm trying to call the array by a pointer:
#include <iostream>
#include "Lottery.h"
#include "Player.h"
#include "LotteryData.h"
using namespace std;
int main()
{
Player player;
Lottery random;
LotteryData data;
player.Input();
random.setRandomNumber();
data.PassInfo(int (&Numbers)[6][6]);
}
Apparently "Numbers" is undefined even though the header is included, here's the header and .cpp files relating to it.
LotteryData.h
#pragma once
#include <iostream>
#include <fstream>
#include "Lottery.h"
#include "Player.h"
using namespace std;
class LotteryData
{
private:
public:
LotteryData();
~LotteryData();
void PassInfo(int (&Numbers)[6][6]);
};
LotteryData.cpp
#include <iostream>
#include <fstream>
#include "LotteryData.h"
using namespace std;
LotteryData::LotteryData()
{
}
LotteryData::~LotteryData()
{
}
void LotteryData::PassInfo(int (&Numbers)[6][6])
{
int* ptr;
FILE *Numfile;
Numfile = fopen("C:/Num.txt", "wb");
ptr = &Numbers[6][6];
for (int i=0; i<36; i++)
{
fwrite(ptr, sizeof(int), 36*36, Numfile);
}
fclose(Numfile);
//ofstream out("Numbers.txt");
}
Everything seems fine, I'm puzzled why the reference in the main says the array is undefined, any ideas?
edit: Apologies, missed some bits
Player.h
#pragma once
#include <iostream>
#include <fstream>
using namespace std;
class Player
{
private:
public:
Player();
~Player();
void Input();
int Numbers[6][6];
};
Player.cpp
#include <iostream>
#include <fstream>
#include "Player.h"
using namespace std;
Player::Player()
{
}
Player::~Player()
{
}
void Player::Input()
{
int num(0);
int duplicate = 0;
int game = 0;
int NumberofGames = 0;
cout<<"How many games do you want to play for this weeks draw?"<<endl;
cin>>NumberofGames;
if (NumberofGames>6)
{
cout<<"Please enter an amount between 1 and 6"<<endl;
cin>>NumberofGames;
}
do
{
for (int i=0;i<6;i++)
{
cout<<"Enter Number "<< (i+1) <<endl;
cin>>num;
if (num > 0 && num <67)
{
Numbers[game][i]= num;
}
else
{
cout <<"Please enter number between 1 and 66"<<endl;
i = i-1;
}
}
game = game + 1;
NumberofGames = NumberofGames - 1;
}
while (NumberofGames=0);
}
void PassInfo(int (&Numbers)[6][6]);
That line does not declare an array - it declares a function. You have no declaration for an array in your class (in fact, you have no data members declared in your class at all).
If you want to declare a member array, you need to modify your class definition:
class LotteryData
{
private:
int Numbers[6][6]; // this declares an array
public:
LotteryData();
~LotteryData();
void PassInfo(int (&arr)[6][6]); // this is still a function declaration
};
Just because you made a function's parameter be named Numbers doesn't magically mean that your program has an array called Numbers declared in it.
So a Player has an array called "Numbers".
Then you would use it like this:
data.PassInfo(player.Numbers);
In your main() function,
data.PassInfo(int (&Numbers)[6][6]);
This is wrong. You should simply pass a reference to 2D array.
int (&Numbers)[6][6];
data.PassInfo(Numbers);
I have a small problem. I'm currently writing a code for tournament handling and I came out with an idea that the best way to keep teams in order in memory will be a list.
Now, I'm trying to sort list cointaing Team class that is containg points records.
Here's the class declaration:
#include "player.h"
#include <string>
class Team {
Player** Gracz;
std::string Name;
int TP, STP;
int Total;
public:
Team();
Team(Player* gracz1, Player* gracz2, Player* gracz3, Player* gracz4, Player* gracz5, Player* gracz6, std::string name);
~Team();
void SetTeam();
void SetTeam(Player gracz1, Player gracz2, Player gracz3, Player gracz4, Player gracz5, Player gracz6, std::string name);
void SetTP(int tp);
void SetSTP(int stp);
std::string GetTeam();
int GetTotal();
int GetTP();
int GetSTP();
bool operator<(Team& team);
bool operator>(Team& team);
void PrintTeam();
};
And here's the program code:
#include <iostream>
#include "player.h"
#include "team.h"
#include <list>
#include <string>
using namespace std;
int main(int argc, char *argv[]) {
Player *p;
Team *t1, *t2, *t3, *t4;
list<Team> x;
list<Team>::iterator it;
p=new Player("a","a","a");
t1=new Team(p,p,p,p,p,p,"A");
t2=new Team(p,p,p,p,p,p,"B");
t3=new Team(p,p,p,p,p,p,"C");
t4=new Team(p,p,p,p,p,p,"D");
x.push_back(*t1);
x.push_back(*t2);
x.push_back(*t3);
x.push_back(*t4);
cout<<"Turniej: "<<endl;
for(it=x.begin();it!=x.end();++it)
cout<<" "<<(*it).GetTeam();
cout<<endl;
t1->SetTP(15);
t2->SetTP(4);
t3->SetTP(8);
t4->SetTP(8);
t3->SetSTP(15);
t4->SetSTP(65);
x.sort();
cout<<"Turniej: "<<endl;
for(it=x.begin();it!=x.end();++it)
cout<<" "<<(*it).GetTeam();
cout<<endl;
return 0;
}
So I'd like to sort list by firstly TPs and then by STPs and it's included in declaration of overloaded operator <. When I'm printing list, I get A,B,C,D before the sorting and the same after the sorting, instead of A,D,C,B after. Where's my mistake?
Thanks for help.
Here the object is copied, and its copy is pushed into a container:
x.push_back(*t1);
/* the same for others */
Here you modify the original object, but the copy in the container is unchanged:
t1->SetTP(15);