I have a Spieler class and a Verein class with a vector of Spieler members.
Now if I change something of the Players like the Staerke(german for strength) by using a function of this class in the player class it does not automatically change the value for this player.
Here is the code:
#include <vector>
#include<iostream>
#include <string>
using namespace std;
class Spieler
{
public:
void setinformation(int a, string b, string c, int d)
{
ID = a;
Vorname = b;
Nachname = c;
Staerke = d;
}
void getinformation()
{
cout << "ID: " << ID << endl;
cout << "Vorname: " << Vorname << endl;
cout << "Nachname: " << Nachname << endl;
cout << "Staerke: " << Staerke << endl << endl;
}
void setStaerke(int x)
{
Staerke = x;
}
int getStaerke()
{
return Staerke;
}
private:
string Vorname, Nachname;
int Staerke, ID;
};
class Verein
{
public:
void setSpielerListe(vector<Spieler> x)
{
Spielerliste = x;
}
vector<Spieler> getSpielerListe()
{
return Spielerliste;
}
string getVereinsName()
{
return VereinsName;
}
int getVereinsID() const
{
return VereinsID;
}
void setVereinsID(int x)
{
VereinsID = x;
}
int getGesamtstaerke()
{
Gesamtstaerke = 0;
vector<Spieler> b;
b = getSpielerListe();
for (size_t i = 0; i < b.size(); i++)
{
Gesamtstaerke = Gesamtstaerke + b[i].getStaerke();
}
return Gesamtstaerke;
}
void Vereinsinformationen()
{
vector<Spieler> list;
int id;
string vereinsname;
int gesamtstaerke;
id = getVereinsID();
vereinsname = getVereinsName();
gesamtstaerke = getGesamtstaerke();
list = getSpielerListe();
cout << "VereinsID: " << id << endl;
cout << "Vereinsname: " << vereinsname << endl;
cout << "Gesamstaerke: " << gesamtstaerke << endl << endl;
cout << "Spieler: " << endl;
for (size_t i = 0; i < list.size(); i++)
list[i].getinformation();
}
private:
vector<Spieler> Spielerliste;
int VereinsID, Gesamtstaerke;
string VereinsName;
};
vector<Spieler> spieler;
int main()
{
Spieler Spieler1;
Spieler1.setinformation(0, "Peter", "Pan", 10);
spieler.emplace_back(Spieler1);
Verein Team1;
Team1.setSpielerListe(spieler);
Spieler1.setStaerke(20);
Team1.Vereinsinformationen();
cin.get();
return 0;
}
I'm really new into c++ and programming so the code might be terrible.
Guess it has to do with pointers, I'm really not into the concept of storing data in c++, try to get it by trial & error; So how to change the Staerke in a way that it is changed in the Teams Playerlist too?
The problem is you are storing full object in the vector and not pointers. When you run this line:
spieler.emplace_back(Spieler1);
a copy of Spieler1 is made and put in the vector. So modifying it in the main will have no effect in the vector. Also not that you are copying the vector when setting in Verein class.
You should use pointer if this is what you are after or better yet have a function to modify strength from Verein class taking its id and new strength as parameters might be a good idea. Something like this:
void setStaerke(int id, int x)
{
vector<Spieler>::iterator it = Spielerliste.begin();
while (it != Spielerliste.end())
{
if ((*it).GetId() == id)
{
(*it).setStaerke(x);
break;
}
}
}
If you have access to C++11, it could be made more elegantly.
Hereby you pass and store a copy from the vector into the object:
Team1.setSpielerListe(spieler);
Therefore changes to the original vector and the contained objects will not affect the member.
Further, I don't have much experience with emplace_back, but the more usual way to append an object to a std::vector would also append a copy:
spieler.push_back(Spieler1);
Therefore changes to the original object would not affect the object you've appended to the container.
Make sure you better understand when objects are copied.
For reference:
http://en.cppreference.com/w/cpp/container/vector/emplace_back
http://en.cppreference.com/w/cpp/container/vector/push_back
How to pass objects to functions in C++?
Related
I am trying to create a program that uses class, arrays, and functions to show information about two students(Name, id#, classes registered). The part I am struggling with is passing arrays to a function. How do I do that?
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
class Student // Student class declaration.
{
private:
string name;
int id;
string classes;
int arraySize;
public:
void setName(string n)
{
name = n;
}
void setId(int i)
{
id = i;
}
void setClasses(string c, int num)
{
classes = c;
arraySize = num;
}
string getName()
{
return name;
}
int getId()
{
return id;
}
void getClasses()
{
for (int counter=0; counter <arraySize; counter++) {
cout << classes[counter] << endl;
}
}
};
int main()
{
//Student 1
string s1Name = "John Doe";
int s1Id = 51090210;
int const NUMCLASSES1 = 3;
string s1Classes[NUMCLASSES1] = {"C++","Intro to Theatre","Stagecraft"};
//Student 2
string s2Name = "Rick Harambe Sanchez";
int s2Id = 666123420;
int const NUMCLASSES2 = 2;
string s2Classes[NUMCLASSES2] = {"Intro to Rocket Science","Intermediate Acting"};
//
Student info;
info.setName(s1Name);
info.setId(s1Id);
//info.setClasses(s1Classes, NUMCLASSES1);
cout << "Here is Student #1's information:\n";
cout << "Name: " << info.getName() << endl;
cout << "ID: " << info.getId() << endl;
//cout << "Classes: " << info.getClasses() << endl;
info.setName(s2Name);
info.setId(s2Id);
// info.setClasses(s2Classes, NUMCLASSES1);
cout << "\n\nHere is student #2's information:\n";
cout << "Name: " << info.getName() << endl;
cout << "ID: " << info.getId() << endl;
//cout << "Classes: " << info.getClasses() << endl;
return 0;
}
The usual way to pass around variable-length lists in C++ is to use an std::vector. A vector is a single object that you can easily pass to a function, copying (or referencing) its contents. If you are familiar with Java, it's basically an ArrayList. Here is an example:
#include <vector>
#include <string>
using namespace std;
class foo {
private:
vector<string> myStrings;
public:
void setMyStrings(vector<string> vec) {
myStrings = vec;
}
}
//...
foo myObj;
vector<string> list = {"foo","bar","baz"};
myObj.setMyStrings(list);
If don't want to use the standard library though, you can pass an array C-style. This involves passing a pointer to the first element of the array, and the length of the array. Example:
void processStrings(string* arr, int len) {
for (int i = 0; i < len; i++) {
string str = arr[i];
//...
}
}
string array[] = {"foo","bar","baz"};
processStrings(array, 3); // you could also replace 3 with sizeof(array)
Passing raw arrays like this, especially if you wanted to then copy the array into an object, can be painful. Raw arrays in C & C++ are just pointers to the first element of the list. Unlike in languages like Java and JavaScript, they don't keep track of their length, and you can't just assign one array to another. An std::vector encapsulates the concept of a "list of things" and is generally more intuitive to use for that purpose.
Life lesson: use std::vector.
EDIT: See #nathanesau's answer for an example of using constructors to initialize objects more cleanly. (But don't copy-paste, write it up yourself! You'll learn a lot faster that way.)
You can pass array of any_data_type to function like this
void foo(data_type arr[]);
foo(arr); // If you just want to use the value of array
foo(&arr); // If you want to alter the value of array.
Use std::vector. Also, don't add functions you don't need. Here's an example of using std::vector
#include <string>
#include <iostream>
#include <vector>
using std::string;
using std::vector;
class Student // Student class declaration.
{
private:
vector<string> classes;
string name;
int id;
public:
Student (const vector<string> &classesUse, string nameUse, int idUse) :
classes (classesUse),
name (nameUse),
id (idUse)
{
}
void print ()
{
std::cout << "Name: " << name << std::endl;
std::cout << "Id: " << id << std::endl;
std::cout << "Classes: ";
for (int i = 0; i < classes.size (); i++)
{
if (i < classes.size () - 1)
{
std::cout << classes[i] << ", ";
}
else
{
std::cout << classes[i] << std::endl;
}
}
std::cout << std::endl;
}
};
int main()
{
Student John ({"C++","Intro to Theatre","Stagecraft"},
"John",
51090210);
John.print ();
Student Rick ({"Intro to Rocket Science","Intermediate Acting"},
"Rick",
666123420);
Rick.print ();
return 0;
}
Name: John
Id: 51090210
Classes: C++, Intro to Theatre, Stagecraft
Name: Rick
Id: 666123420
Classes: Intro to Rocket Science, Intermediate Acting
In the private variables of class Student, you are storing a string:
String classes;
where as you should be storing an array of strings like:
String classes[MAX_NUM_CLASSES];
then in the set classes function, pass in an array of strings as the first argument, so it should be :
void setClasses(string[] c, int num)
{
classes = c; //not sure if simply setting them equal will work, rather copy entire array using a for loop
arraySize = num;
}
This should point you in the right direction
Also, use std::vector instead of string[], it will be easier.
I am needing help with polymorphism. I have no clue how to work with this. I have to write a program that creates an Orc and a Human and demonstrates the behavior of the classes. I am just needing some help with setting this program up. I have set up the classes with the information, but how do I get the createCharacter function to work? Would I have characterTotal = characterStrength + characterDexterity + characterIntelligence in the createCharacter function? I know my program is not correct right now and I have some errors and things, but I am still just trying to get a better understanding of this.
UPDATE:
I am having trouble with the createCharacter function. It is a pure virtual function and I am needing some help on how to get it to work.
For Human class createCharacter will:
Get the values of STR, DEX and INT. Will calculate the total of the values.
(Let’s assume STR = 17, DEX = 12 and INT = 10. It will store 37 into characterTotal.Itwill print out a message: “The strong human Paladin, has a total scoreof 37.” (Strong adjective comes due to STR being 17. If something is above 17 you should say something related. STR = strong, DEX = dexterous, INT =
intelligent).
For Orc class createCharacter will:
Get the values of STR, DEX and INT. Will calculate the total of the values.
However Orcs receive -2 to INT and DEX. They receive +2 to STR. (Let’s
assume STR = 16, DEX = 10 and INT = 8. It will store 16+2,10-2,8-2 = 28 into
characterTotal.
It will print out a message “The berserker Orc has a total score of 28.” (Here the
Orcs get their adjectives from their clan names so you do not need to do
something specific to STR, DEX or INT.)
CODE:
//character.h
#ifndef CHARACTER_H
#define CHARACTER_H
using namespace std;
class Character
{
protected:
float characterTotal;
public:
virtual void createCharacter() = 0; //Pure virtual function
};
#endif
//human.h
#ifndef HUMAN_H
#define HUMAN_H
#include "Character.h"
using namespace std;
class Human
{
private:
int characterStrength;
int characterDexterity;
int characterIntelligence;
string characterType;
public:
Human();//Constructor
int getStength
{
cout << "Enter a number from 0 to 18\n";
cin >> characterStrength;
return characterStrength;
}
int getDexterity
{
cout << "Enter a number from 0 to 18\n";
cin >> characterDexterity;
return CharacterDexterity;
}
int getIntelligence
{
cout << "Enter a number from 0 to 18\n";
cin >> characterIntelligence;
return characterIntelligence;
}
string getType
{
cout << "Please choose one of the following\n";
cout << "A -- Paladin \n";
cout << "B -- Ranger \n";
cout << "C -- Wizard \n";\
cin >> characterType;
return characterType;
}
};
#endif
//orc.h
#ifndef ORC_H
#define ORC_H
#include "Character.h"
#include "Human.h"
using namespace std;
class orc
{
private:
int characterStrength;
int characterDexterity;
int characterIntelligence;
string characterClan;
public:
orc(); //Constructor
int getStrength
{
cout << "Enter a number between 0 to 18\n";
cin >> characterStrength;
return characterStrength;
}
int getDexterity
{
cout << "Enter a number between 0 to 18\n";
cin >> characterDexterity;
return characterDexterity;
}
int getIntelligence
{
cout << "Enter a number between 0 to 18\n";
cin >> characterIntelligence;
return characterIntelligence;
}
string getClan
{
cout << "Please choose one of the following\n";
cout << "A -- Barbarian \n";
cout << "B -- Berserker \n";
cout << "C -- Vanguard \n";\
cin >> characterClan;
return characterClan;
}
};
#endif
Example: A class called Account posesses a container with Character. Your classes Human and Orc inherit both from Character. Inside of your Human class you may want to set spell ABC to all characters which are created (in createCharacter). But if the player creates an Orc, you might want to set another spell XYZ to it, instead of ABC. Base classes come in handy here. In this example you see one of these abstract functions in action (Character::initCharacter).
You can put in more abstract functions inside of Character IF the classes which are supposed to inherit from Character MUST / NEED TO implement these functions.
This is only an example. If you want to do it properly, you need more than this and would have to modify all for database access and further abstraction.
enum CharacterType
{
CHAR_INVALID = 0x0,
CHAR_HUMAN = 0x1,
CHAR_ORC = 0x4
};
class Character
{
public:
Character(unsigned int charGUID) //You might want to set data in the constructor already
: m_charGUID(charGUID) //right after it has been load from Account::LoadAccountInformation()
{
std::cout << "Constructor of \"Character\"" << std::endl;
}
virtual ~Character(void) //Cleanup if needed
{
std::cout << "Destructor of \"Character\"" << std::endl;
}
virtual void createCharacter(void) = 0;
virtual void initCharacter(void) = 0;
CharacterType GetTypeID(void)
{ return m_typeID; }
protected:
void SetTypeID(CharacterType ct)
{ m_typeID = ct; }
private:
Character(const Character &);
unsigned int m_charGUID;
CharacterType m_typeID;
};
class Human : public Character
{
public:
Human(unsigned int charGUID)
: Character(charGUID)
{
SetTypeID(CHAR_HUMAN);
std::cout << "Constructor of \"Human\"" << std::endl;
}
virtual ~Human(void) //Cleanup if needed
{
std::cout << "Destructor of \"Human\"" << std::endl;
}
void createCharacter(void) override
{
//Set data...
}
void initCharacter(void) override
{
std::cout << "You initialized a character of type \"Human\"" << std::endl;
}
};
class Orc : public Character
{
public:
Orc(unsigned int charGUID)
: Character(charGUID)
{
SetTypeID(CHAR_ORC);
std::cout << "Constructor of \"Orc\"" << std::endl;
}
virtual ~Orc(void) //Cleanup if needed
{
std::cout << "Destructor of \"Orc\"" << std::endl;
}
void createCharacter(void) override
{
//Set data...
}
void initCharacter(void) override
{
std::cout << "You initialized a character of type \"Orc\"" << std::endl;
}
};
class Account
{
public:
Account(unsigned int accountGUID)
{ m_accGUID = accountGUID; }
//#Return: False if load from database failed
bool LoadAccountInformation(void) //You could give it data also
{
//You could also load data directly from a database here if you'd like to
//Here are just some sample values (partially hardcoded)
characters.clear();
const int charsOnAccount = 1; //Load from database
for (int i = 0; i < charsOnAccount; ++i)
{
CharacterType ct = CHAR_HUMAN; //Load from database
unsigned int characterGUID = i;
switch (ct)
{
case CHAR_HUMAN:
{
characters[characterGUID] = std::move(std::shared_ptr<Character>(new Human(characterGUID)));
} break;
case CHAR_ORC:
{
characters[characterGUID] = std::move(std::shared_ptr<Character>(new Orc(characterGUID)));
} break;
default:
{
std::cout << "Invalid character type: " << ct << std::endl; //Or log to file
} break;
}
}
return true;
}
void InitCharacters(void)
{
for (auto itr = std::begin(characters); itr != std::end(characters); ++itr)
itr->second->initCharacter();
}
private:
//A unique account-GUID
unsigned int m_accGUID;
//Let's say a unique char-GUID and the Character object
std::map<unsigned int, std::shared_ptr<Character> > characters;
//And more information...
};
int main(int argc, char *argv[])
{
Account ac = Account(1);
ac.LoadAccountInformation();
ac.InitCharacters();
return 0;
}
I would like to take the return value from the function on the top and then do something with it in the function on the bottom. What should I put in the bottom function to use the value that was returned from "loadVectorWithReturn"
I do realize that I could create a new variable and store it there for later recall but I am trying to do more complicated things now.
Thank you
double vectors1::loadVectorWithReturn() {
vectors1 v1;
for (int i = 0; i <= 10; i++) {
v1.value.push_back(i);
cout << v1.value[i] << ", ";
}
cout << endl;
cout << v1.value[5] << endl;
return v1.value[5];
}
double doSomethingWithVectorReturn(TAKE IN VALUE FROM loadVectorWithReturn) {
//do something with v1.value[5];
}
If you are saying, "I don't want to make a global variable for v1", you could do this.
double vectors1::loadVectorWithReturn() {
vectors1 v1;
for (int i = 0; i <= 10; i++) {
v1.value.push_back(i);
cout << v1.value[i] << ", ";
}
cout << endl;
cout << v1.value[5] << endl;
return v1.value[5];
}
double vectors1::doSomethingWithVectorReturn() {
int returned = loadVectorWithReturn();
//Do something with returned.
}
Note: the "vectors1::" in front of "doSomethingWithVectorReturn" allows "doSomethingWithVectorReturn" to use the "loadVectorWithReturn" function.
Keep in mind that if you are only using the "returned" value one time (or multiple although that can be slower in many cases), you could skip setting the variable and just use "loadVectorWithReturn()" in place of it.
Example (Simply cout's the value):
double vectors1::doSomethingWithVectorReturn() {
cout << loadVectorWithReturn();
}
I am feeling like you are needing this because you will use loadVectorWithReturnlater within doSomethingWithVectorReturn in some point.
If this is the situation we can use:
#include <iostream>
#include <functional>
struct A
{
int fooA() const
{
return 5;
}
};
void doSomethingWithA( std::function<int()> foo )
{
std::cout << foo();
}
int main()
{
A a;
doSomethingWithA([a]()
{
return a.fooA();
});
}
I am creating a vector that contains pointers to a base class. In this vector I'm dynamically storing pointers to derived classes which contain some member variables, one of them being a string variable name.
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
bool hasDirection = false;
bool hasDiameter = false;
int direction;
float diameter;
int starDimension = 0;
int animalDimension = 0;
int fishDimension = 0;
class MovingObject
{
protected:
std::string name;
int direction;
float diameter;
int dimension;
float movingSpeed;
public:
std::string getName(){ return name;};
int getDirection(){ return direction;};
float getDiameter(){ return diameter;};
float getMovingSpeed(){ return movingSpeed;};
int getDimension(){ return dimension;};
void setName(std::string v){ name = v;};
void setDirection(int d){ direction = d;};
void setDiameter(float f){ diameter = f;};
void setMovingSpeed(float s){ movingSpeed = s;};
void setDimension (int d){ dimension = d;};
virtual void PrintContents()=0;
};
static std::vector<MovingObject*> data;
class starObject : public MovingObject
{
public:
void PrintContents()
{
std::cout << "(" << getName() << "," << getDiameter() << "," << getDirection() << ")";
}
};
class animalObject : public MovingObject
{
public:
void PrintContents()
{
std::cout << "(" << getName() << "," << getDiameter() << "," << getDirection() << ")";
}
};
class fishObject : public MovingObject
{
public:
void PrintContents()
{
std::cout << "(" << getName() << "," << getDiameter() << "," << getDirection() << ", [" << getDimension() << "], " << getMovingSpeed() << ")";
}
};
I later set all these member variables inside a main function. The problem is when I try to output the contents of the member variables, all of them show up except for the string name.
Now, I've checked to make sure that the string gets set before calling the PrintContent() method, and it shows that the value is in the vector. However, when I debug through the code, the value is no longer there, instead containing an empty string.
Could someone with better c++ knowledge explain to me why this is happening? This is the main class:
int main()
{
std::string type;
Reader reader;
while (!std::cin.eof())
{
try
{
std::string type;
std::cin >> type;
if (type =="int")
{
reader.ReadDirection();
}
else if (type =="float")
{
reader.ReadDiameter();
}
else if (type == "string")
{
std::string name;
std::cin >> name;
if (hasDirection && hasDiameter)
{
int dimension;
if (diameter > 0 && diameter < 10)
{
//fish
fishObject fish;
fish.setName(name);
fish.setDiameter(diameter);
fish.setDirection(direction);
dimension = fishDimension;
fishDimension += 50;
fish.setDimension(dimension);
fish.setMovingSpeed(0.1);
data.push_back(&fish);
}
else if (diameter >= 10 < 500)
{
//animal
animalObject animal;
animal.setName(name);
animal.setDiameter(diameter);
animal.setDirection(direction);
dimension = animalDimension;
animalDimension += 800;
animal.setDimension(dimension);
animal.setMovingSpeed(5.0);
data.push_back(&animal);
}
else if (diameter >=500)
{
//star
starObject star;
star.setName(name);
star.setDiameter(diameter);
star.setDirection(direction);
dimension = starDimension;
starDimension += 5000;
star.setDimension(dimension);
star.setMovingSpeed(30.0);
data.push_back(&star);
}
}
else
{
throw (IncompleteData(name));
}
}
}
catch (IncompleteData e)
{
std::cerr << "No diameter or direction given for object " << e.objectName << "\n";
}
}
The objects you push to the data vector are local because they are declared inside if/else blocks (see the declarations of fish and animal).
When you push the address of such an object to the vector, it will continue to point to the local object, which ceases to exist at the end of the local scope. You need to create objects that live beyond the local scope. One way of doing this is to create copies of the local objects on the heap and push those to the vector:
data.push_back(new fishObject(fish));
Of course this means that you get a memory leak unless you make sure you explicitly delete the elements of the vector some time before the end of the program. The usual recommendation to avoid having to think of this is to use a vector of std::unique_ptr<MovingObject> instead of a vector of naked pointers.
I have the following code written in C++:
#include<iostream>
#include<vector>
using namespace std;
class cViews {
string viewName;
double minD;
vector<double> dss;
public:
string minInput1, minInput2;
cViews(string);
cViews();
void setName(string s) { viewName = s; }
string getName() { return viewName; }
void setMinI(string m) { minInput1 = m; }
string getMinI() { return minInput1; }
void setMinD(double d) { minD = d; }
double getMinD() { return minD; }
void addD(vector<double> k){ dss = k; }
vector<double> getD(){ return dss; }
};
cViews::cViews(string str) {
viewName = str;
vector<double> dss = vector<double>();
}
cViews::cViews() {
vector<double> dss = vector<double>();
}
class Obj{
string name;
cViews dist;
public:
Obj(string);
void setName(string s) { name = s; }
string getName() { return name; }
void addDist(cViews k){ dist = k; }
cViews getDist(){ return dist; }
};
Obj::Obj(string str) {
name = str;
cViews dist();
}
void changeViewN(cViews *v, string s){
v->setMinI(s);
}
int main(){
Obj o1("Object1");
cViews v3;
cViews v1("View 1");
v1.setMinI("View 2");
v1.setMinD(1);
o1.addDist(v1);
cout << o1.getName() << " " << o1.getDist().getMinI() << endl;
v3 = o1.getDist();
changeViewN(&v3, "Changed");
cout << o1.getName() << " " << o1.getDist().getMinI() << endl;
return 0;
}
Output is:
Object1 View 2
Object1 View 2
The problem here is I am trying to change the value of an object that was created within another object.
Output should be:
Object1 View 2
Object1 Changed
Any help is greatly appreciated. Thank you.
To change the object and not a copy, ou have to use pointers or references. Else you just copy the object returned from getDist() and thus cant change the original object.
cViews* getDist(){ return &dist; }
...
changeViewN(o1.getDist(), "Changed");
It seems you got a couple of problems, the first few:
cViews::cViews(string str) {
vector<double> dss = vector<double>();
}
viewName isn't initialized, dss is Declared in the function (which is meaningless as it will be scrapped as soon as the function returns).
ps. you would like to change the second line like this:
cout << o1.getName() << " " << o1.getDist().getMinI() << endl;
to
cout << o2.getName() << " " << o2.getDist().getMinI() << endl;
You should really proofread your code ...