Creating Multiple Dynamically Allocated objects in C++ - c++

Another question for those far wiser than I:
I'm trying to create 3 instances of a Player Class like so:
Player *player1 = new Player("Aaron",0.3333333);
Player *player2 = new Player("Bob",0.5);
Player *player3 = new Player("Charlie",1);
You can see their constructor below. It's really simple:
Player::Player(string n, double hr)
{
name = n;
hitrate = hr;
}
(just assume name and hitrate are defined properly)
Now my problem is this, when I try to check each individual player for their name, it seems they have all become aliases of sorts for player3
//Directly after the player instantiations:
cout << player1->getName() << "\n";
cout << player2->getName() << "\n";
cout << player3->getName() << "\n";
//In the Player.cpp file:
string Player::getName(){
return name;
}
Outputs:
Charlie
Charlie
Charlie
Alright, so I'd really like to know the best solution to get around this problem but more importantly I just want to understand why it's behaving this way. It seems like such a simple thing (being spoiled by java as I am).
Also it's important to note: this is for a school assignment and I am told that I MUST use dynamically allocated objects.
Thanks so much, and do let me know if anything needs clarifying.
Edit: By demand, here are the full files:
PlayerTest.cpp
#include <iostream>
#include <player.h>
using namespace std;
int main(){
Player *player1 = new Player("Aaron",0.3333333);
Player *player2 = new Player("Bob",0.5);
Player *player3 = new Player("Charlie",1);
cout << player1->getName() << "\n";
cout << player2->getName() << "\n";
cout << player3->getName() << "\n";
return 0;
}
Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include <string>
using namespace std;
class Player
{
public:
Player(string, double);
string getName();
};
//Player.cpp
#include "Player.h"
string name;
double hitrate;
Player::Player(string n, double hr)
{
name = n;
hr = hitrate;
}
string Player::getName(){
return name;
}
#endif // PLAYER_H

The name and hitrate variables need to be inside the Player class declaration so that each object gets its own separate copies.
class Player
{
public:
Player(string, double);
string getName();
private:
string name;
double hitrate;
};

Related

Calling a string getter function from a header file

I'm learning C++, and I'm just messing around with putting classes in separate files for practice. I have a getter function, which returns a string (because the variable is saved as a string). However, from my main() function, I am not sure how to call it. I know the problem is probably that I need to include string somewhere when I call the object, but I have no idea how to format it.
I know this is a pretty newbie questions, but I couldn't find the answer anywhere. Could someone help me out?
(p.s. I'm not trying to get this specific code to work, since it's useless. I'm just trying to learn how to apply it for future reference).
I've tried throwing in string in a couple of places when calling or creating the object, but I always get an error. I know I could get around it by not encapsulating the variable or not having a separate class file, but that's not what I want.
main.cpp
#include <iostream>
#include "usernameclass.h"
#include <string>
using namespace std;
int main()
{
usernameclass usernameobject;
usernameobject.getUsername();
return 0;
}
usernameclass.h
#ifndef USERNAMECLASS_H
#define USERNAMECLASS_H
#include <string>
class usernameclass
{
public:
usernameclass();
std::string getUsername();
void setUsername(std::string name);
askUsername();
private:
std::string usernameVar = "test";
};
#endif
usernameclass.cpp
#include "usernameclass.h"
#include <iostream>
#include "username.h"
#include <string>
using namespace std;
string usernameclass::getUsername(){
return usernameVar;
cout << "test cout" << endl;
}
usernameclass::askUsername(){
string name;
cout << "What is your name?" << endl;
cin >> name;
setUsername(name);
cout << "Ah, so your name is "+usernameVar+", great name I guess!" << endl;
cin.get();
cin.get();
cout << "You're about to do some stuff, so get ready!" << endl;
}
usernameclass::usernameclass(){}
void usernameclass::setUsername(string name){
string* nameptr = &usernameVar;
*nameptr = name;
}
Expected result: runs getUsername() function and returns usernameVar
Actual result: doesn't run the getUsername() function
The current code would not compile, because you have not specified return type of 'askUsername()' routine, which is 'void', I believe.
Other things are good, apart from an output in 'getUsername()', which happens after returning from the function and about which you should have received a warning, I guess.
To the question: you can call that 'get' method in 'main()' as:
cout << usernameobject.getUsername();
Your code should be structured more like this instead:
main.cpp
#include <iostream>
#include "usernameclass.h"
int main()
{
usernameclass usernameobject;
// optional:
// usernameobject.askUsername();
// do something with usernameobject.getUsername() as needed...
return 0;
}
usernameclass.h
#ifndef USERNAMECLASS_H
#define USERNAMECLASS_H
#include <string>
class usernameclass
{
public:
std::string getUsername() const;
void setUsername(std::string name);
void askUsername();
private:
std::string usernameVar = "test";
};
#endif
usernameclass.cpp
#include <iostream>
#include "usernameclass.h"
std::string usernameclass::getUsername() const {
return usernameVar;
}
void usernameclass::setUsername(std::string name) {
usernameVar = name;
}
void usernameclass::askUsername() {
std::string name;
std::cout << "What is your name?" << std::endl;
std::getline(std::cin, std::name);
setUsername(name);
std::cout << "Ah, so your name is " << getUsername() << ", great name I guess!" << std::endl;
std::cout << "You're about to do some stuff, so get ready!" << std::endl;
}

C++: No matching function to call to const char

im trying to create a object called player in class player.
#include <string>
#ifndef PLAYER_HH
#define PLAYER_HH
using namespace std;
class Player
{
public:
Player(string name, int points);
const string get_name();
int get_points();
void add_points(int pts);
bool has_won();
private:
string _name;
};
#endif // PLAYER_HH
from player.cpp:
#include <string>
using namespace std;
Player::Player(string name):
_name(name), _points(0){
}
Now, the problem is, in the main function i get this error:
error: no matching function for call to ‘Player::Player(const char [6])’
Player player1 = Player("Matti");
^
Shouldn't the compiler be able to convert it to a string?
edit: Here is the full main.cpp that i'm not supposed to be changing:
#include <cstdlib>
#include <iostream>
#include <string>
#include "player.hh"
int main()
{
Player player1 = Player("Matti");
Player player2 = Player("Teppo");
Player* in_turn = 0;
int turn = 1;
while (true)
{
if (turn % 2 != 0)
{
in_turn = &player1;
}
else
{
in_turn = &player2;
}
std::cout << "Enter the score of player " << in_turn->get_name()
<< " of turn " << turn << ": ";
int pts = 0;
std::cin >> pts;
in_turn->add_points(pts);
if (in_turn->has_won())
{
std::cout << "Game over! The winner is " << in_turn->get_name() << "!" << std::endl;
return EXIT_SUCCESS;
}
std::cout << std::endl;
std::cout << "Scoreboard after turn " << turn << ":" << std::endl;
std::cout << player1.get_name() << ": " << player1.get_points() << "p" << std::endl;
std::cout << player2.get_name() << ": " << player2.get_points() << "p" << std::endl;
std::cout << std::endl;
turn += 1;
}
return EXIT_SUCCESS;
}
You guys are awesome with your fast answers :-)
You declared the constructor of player as Player(string name, int points);.
If you define a function with two parameters you have to use both.
Create your object with
Player player1 = Player("Matti", 0);
If you still want to call it with just one parameter you have to set a default value like this.
class Player
{
public:
...
Player(string name, int points = 0); // replace 0 with whatever you want to be default.
...
}
Then you can use both variants. The one above and the one you attempted
Player player1 = Player("Matti");
Of course the function header of your definition has to match the one in the declaration:
Player::Player(string name, int points):
_name(name), _points(points){
}
It's important not to write the default value inside dhe definition because this will most likely produce an compiler error.
The conversion from const char[6] to std::string will work and is not the issue here.
Your constructor has two parameters, you cannot simply omit the second one. If you like to create Player objects with a default score, declare your constructor as:
Player(string name, int points = 0);
First of all, you declare your constructor having two parameters:
Player(string name, int points);
but define it as having only one:
Player::Player(string name):
_name(name), _points(0){
}
That should give you compilation error. Either remove the second param from the declaration in class body and keep main.cpp as it is or add second param to the definition in player.cpp:
Player::Player(string name, int points):
_name(name), _points(points){
}
and then specify value for 'points' explicitly:
Player("Matti", 0);
You can also have both - just add default value for points:
class Player
{
...
Player(string name, int points = 0);
};
Then, both of these lines will work:
Player player1 ("Matti");
Player player2 ("Matti", 0);

Unable to change private variable's content

main.cpp :
#include <iostream>
#include <string>
#include "Players.h"
using namespace std;
int main ()
{
cout << "**** Welcome to Leviathan's first TicTacToe Game! ****\n\n";
Players getNamesobject;
Players printNamesobject;
getNamesobject.getPlayersNames();
printNamesobject.printPlayersNames();
}
Players.h:
#ifndef PLAYERS_H
#define PLAYERS_H
class Players
{
public:
void getPlayersNames();
void printPlayersNames();
private:
std::string _player1Name;
std::string _player2Name;
};
#endif // PLAYERS_H
Players.cpp :
#include <iostream>
#include <string>
#include "Players.h"
using namespace std;
void Players::getPlayersNames()
{
string p1,p2;
cout << "Enter player 1 name : ";
cin >> p1;
cout << "\nEnter player 2 name : ";
cin >> p2;
_player1Name = p1;
_player2Name = p2;
}
void Players::printPlayersNames()
{
cout << "Alright " << _player1Name << " and " << _player2Name <<", the game has begun!\n\n";
}
When i run this, and enter two names, the _player1Name and _player2Name variables don't get changed. I've tried setting them a string manually and they get printed normally. Can anyone explain what's wrong here? It seems like getPlayerNames function can't change the private variables?
It's because you have two different objects!
One that you set the member variables in (through the getPlayersNames function), and another unrelated object you use to print a different set of variables.
You should have a single object, and call getPlayersNames and printPlayersNames on that single object. Like
Players playersObject;
playersObject.getPlayersNames();
playersObject.printPlayersNames();
Each instance of the Players object you create will have its own set of member variables that are tied to that single object, member variables are not shared between objects (unless you make them static).

Passing a class object to a list table

I have a struct list, a class castomer. I want to store my castomer to the list. For that I am creating a castomer each time and I strore them to a list table. There are no errors except that the program crashes each time I try to store a castomer into my table.
I have this list and class:
class castomer{
private:
string name;
string lastname;
int number;
double time;
public:
void setAll(string,string,int,double);
int numberR(){return number;}
double timeR(){return time;}
void displayAll();
};
struct node {
castomer person;
struct node *next;
};
This function for adding castomer:
void add(clock_t *start,struct node *table[])
{
*start = clock();
double time=(double)*start;
int i=0;
while(table[i]!=NULL)
{
i++;
}
if(i > 24)
cout << "We are not able to add another castomer becase we are full please wait for ont to go "<<endl;
else{
castomer c1;
cout<<i;
cout<< "Give me the castomers name and lastname :";
string temp1,temp2;
cin>>temp1;
cin>>temp2;
c1.setAll(temp1,temp2,i,time);
table[i]->person=c1;//my program crases here anyone knows why?
}
}
ps: In my main the table[] looks like this struct node * table[25];
struct node* table[25]
This is declaring table to be an array of 25 pointers. You have to allocate memory for each of these pointers which from looking at your code is missing.
After your while-loop, table[i] will be NULL.
table[i]->person = c1; // Your program crashes here because of that.
Using your code as it is, you should do
table[i] = new node;
table[i]->person = c1;
But the code looks very strange, like you want to implement a linked list (the node structure) but are sticking to using arrays for some reason.
If you're aiming for a linked list, you need to rethink a lot of your code.
If you're not, you can lose the node type completely.
Since you are using (or trying to use) C++ I will make mention of a few things you can do to improve your code and make your own life easier.
In C++ you can define constructors for initializing objects.
Your function setAll is a bad practice. You don't really want to change all data of a person after you have created. You just want to initialize the data at creation time. Well use constructors.
You don't need pointers
For what you want to do you don't need complicate the code using pointers you could pass the arguments by reference.
You are using C++, use STL
Specifically vector I guarantee it, will help you.
Use cout << for displaying yuor object
you could add a friend ostream& operator<< function to your class in order to be able to write code like:
Customer a;
cout << a << endl;
A complete example:
#include <iostream>
#include <vector>
#include <ctime>
#include <string>
using namespace std;
class Customer
{
public:
Customer(){} // default constructor.
Customer(string pname, string plastname): name(pname), lastname(plastname)
{
id = ++idgen; // Set an id number.
time = (double)clock(); // initialize time.
}
int getId() {return id;} // former numberR().
double getTime() {return time;} // former timeR().
friend ostream& operator<<(ostream &out, Customer obj)
{out << obj.name << " " << obj.lastname << ". " << "Id: " << obj.id << " Time: " << obj.time;}
private:
static int idgen; // static values are a good way for keep some sort of id.
int id; // former member: number.
double time; // Why don't use clock_t directly?
string name, lastname;
};
int Customer::idgen = 0; // Initialize static variable.
int main()
{
int const MAX_NUMBER_PERSONS = 2;
std::vector<Customer> customer_list;
string name, lastname;
while (customer_list.size() < MAX_NUMBER_PERSONS)
{
cout << "Give me the castomers name and lastname <name> <lastname>:";
cin >> name >> lastname;
customer_list.push_back(Customer(name, lastname));
}
for (auto &x: customer_list) // If you're learnign C++ its a good moment for search
{ // for c++11 doc.
cout << x << endl;
}
return 0;
}

Strange behavior for int / counter

I'm trying to add some songs to a vector inside a class. One of the values I'm storing is an int representing the song. It's essentially a counter. The first song I add should have the value 1, the second value two and so forth. But It's getting other strange values like big random numbers (positives and negatives). I can't wrap my head around what I'm doing wrong. This is the code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Jukebox{
public:
void addSong(string artist, string title, string filename) {
song s {++songCounter, artist, title, filename};
Songs.push_back(s);
}
void printSong (int song) {
cout << Songs[song].no << ". ";
cout << Songs[song].artist << " - ";
cout << Songs[song].title << " : ";
cout << Songs[song].filename << endl;
}
private:
struct song {
int no;
string artist;
string title;
string filename;
};
vector<song> Songs;
int songCounter;
};
int main() {
Jukebox jbox;
jbox.addSong("U2", "Magnificent", "U2-Magnificent.mp3");
jbox.addSong("Sting", "Englishman in New York", "Sting-Englishman_in_New_York.mp3");
jbox.addSong("U2", "One", "U2-One.mp3");
jbox.printSong(0);
jbox.printSong(1);
jbox.printSong(2);
return 0;
}
Update
Ok, I'm probably stupid and should read more about classes before trying to implement this. But I think I did read and I still don't get it. This is what my class looks like now (which won't work):
class Jukebox(): songCounter(0)
{
public:
void addSong(string artist, string title, string filename) {
songCounter++;
song s {songCounter, artist, title, filename};
Songs.push_back(s);
}
void printSong (int song) {
cout << Songs[song].no << ". ";
cout << Songs[song].artist << " - ";
cout << Songs[song].title << " : ";
cout << Songs[song].filename << endl;
}
private:
int songCounter;
struct song {
int no;
string artist;
string title;
string filename;
};
vector<song> Songs;
};
Final word
Ok. From the example I've seen of c++ contructor classes I had some kind of wrong impression of how they worked. Now I think I'm getting it a little bit more. But the syntax still seems strange to me. But I try to read more so I really understand it. Here is what I did and to seems to work:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Jukebox {
public:
void addSong(string artist, string title, string filename) {
songCounter++;
song s {songCounter, artist, title, filename};
Songs.push_back(s);
}
void printSong (int song) {
cout << Songs[song].no << ". ";
cout << Songs[song].artist << " - ";
cout << Songs[song].title << " : ";
cout << Songs[song].filename << endl;
}
Jukebox(): songCounter(0) {} // Constructor
private:
int songCounter;
struct song {
int no;
string artist;
string title;
string filename;
};
vector<song> Songs;
};
int main() {
Jukebox jbox;
jbox.addSong("U2", "Magnificent", "U2-Magnificent.mp3");
jbox.addSong("Sting", "Englishman in New York", "Sting-Englishman_in_New_York.mp3");
jbox.addSong("U2", "One", "U2-One.mp3");
jbox.printSong(0);
jbox.printSong(1);
jbox.printSong(2);
return 0;
}
You did not initialize songCounter in your constructor.
Jukebox(): songCounter(0),//....other members
If you do not initialize it, then it may have any random value and that leaves your program in an Undefined State.
Always be careful while using unitialized variables, it often leads to Undefined Behavior and your program is a good example of it.
Also, I am not sure of your design but probably it should be a static member if you want to use it as a counter, which maintains state for all objects of your Song class.
Or
You will have to explicitly set it to a proper value at time of creating a Song object.
Okay its a counter for JukeBox and not Song class so its still okay to be a member.
You didn't initialize the variable songCounter.
Add the following to the class definition of Jukebox:
Jukebox(): songCounter(0) {}
you need a constructor for Jukebox and in that you need to initialise the counter to 0.
I think you should initialize songCounter to be 0. In the public part of the class:
public Jukebox() : songCounter(0) {}
Where do you initialise songCounter? In C++, primitives aren't zero initialised by default. You need to add
: songCounter(0)
to your constructor.