Read the comments too.
Basically, I am trying to figure out object constructors, destructor, and classes. I created a class with a few public member variables, and a few private member variables. At this point I am only utilizing the public members within my code.
My question is, to put it quite simply, how do I utilize the constructor, destructor, and print off the objects info to the console.
Thanks.
#include <iostream>
// Class -> NPC
// Contains generic stats for an NPC in a game
class NPC
{
public:
char name;
int age;
char favoriteItem;
private:
char quest;
char nemesis;
int karma;
}
// Object Constructor
NPC::NPC (char newName, int newAge, char newFavoriteItem)
{
name = newName;
age = newAge;
favoriteItem = newFavoriteItem;
}
// Object Deconstructor
NPC::~NPC()
{
// Do nothing
}
// Here I would like to create a new NPC, bob, with a name of "Bob", age of 28, and his favorite items being a Sword
// Next, I attempt to use this information as output.
int main()
{
NPC bob("Bob",28, "Sword");
std::cout << bob << std::endl;
}
Fixed the char (only one character) to std::string. I added initialization list and std::ostream &operator << operator.
http://en.cppreference.com/w/cpp/language/default_constructor
#include <iostream>
#include <memory>
#include <string.h>
class NPC
{
public:
std::string name;
int age;
std::string favoriteItem;
NPC(std::string const& name, int age, std::string favoriteItem)
: name(name), age(age), favoriteItem(favoriteItem)
{};
private:
char quest;
char nemesis;
int karma;
};
std::ostream &operator << (std::ostream &os, NPC const& npc)
{
os << npc.name << " " << npc.age << " " << npc.favoriteItem << "\n";
return os;
};
int main()
{
NPC npc("Bob", 28, "Sword");
std::cout << npc;
return 0;
}
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
#include<iostream>
using namespace std;
class player{
private:
string name;
int health;
int xp;
public:
void names (string get_name, int get_health, int get_xp){
name=get_name;
health=get_health;
xp=get_xp;
}
};
int main(){
player p;
p.names("Mohit",100,3);
cout<<p.health<<endl;
cout<<p.xp<<endl;
cout<<p.name<<endl;
player *hero = new player();
hero ->names("Tavishi",1000,3);
cout<<(*hero).name<<endl;
cout<<(*hero).xp<<endl;
cout<<(*hero).health<<endl;
delete hero;
return 0;
}
I am accessing the attributes within the class only, then why am I getting the error regarding the private access specifier??
Here's your code, fixed up a bit:
#include <iostream>
#include <string> // Include what you use
class player {
private:
std::string name;
int health;
int xp;
public:
void names(std::string get_name, int get_health, int get_xp) {
name = get_name;
health = get_health;
xp = get_xp;
}
// Simplest fix: Getters
std::string get_name() const { return name; }
int get_health() const { return health; }
int get_xp() const { return xp; }
};
int main() {
player p;
p.names("Mohit", 100, 3);
// cout<<p.health<<endl; // Not "within the class"
// cout<<p.xp<<endl; // Not "within the class"
// cout<<p.name<<endl; // Not "within the class"
std::cout << p.get_health() << '\n'
<< p.get_xp() << '\n'
<< p.get_name() << '\n';
player *hero = new player();
hero->names("Tavishi", 1000, 3);
std::cout << hero->get_name() << '\n'; // Prefer arrow operator over (*).
std::cout << hero->get_xp() << '\n';
std::cout << hero->get_health() << '\n';
delete hero;
return 0;
}
You were using an object in the main() function, which is not "within the class" to attempt to access private members. When people say that you can use private members directly "within the class" they mean from within a class member function. Anything else is considered "out of the class" and the private/public restrictions are enforced.
If you need access to them, you can provide getter functions in your class, which is what I did.
Here's your code again, this time better utilizing C++. Namely, constructors and operator overloading.
#include <iostream>
#include <memory>
#include <string> // Include what you use
class player {
private:
std::string name{}; // Default member initialization makes default ctor
int health = 0; // easy to implement
int xp = 0;
public:
// Provide constructors for easier initialization
player() = default;
player(std::string name, int health, int xp)
: name(name), health(health), xp(xp) {}
// void names(std::string get_name, int get_health, int get_xp) {
// name = get_name;
// health = get_health;
// xp = get_xp;
// }
// Simplest fix: Getters
// ** Getter may not be necessary anymore if your only purpose is printing
std::string get_name() const { return name; }
int get_health() const { return health; }
int get_xp() const { return xp; }
// If you want to cout object directly, provide operator<<()
// Friends can access private members directly; they are **not** class members
friend std::ostream& operator<<(std::ostream& sout, const player& p) {
return sout << p.health << '\n' << p.xp << '\n' << p.name << '\n';
}
};
int main() {
player p{"Mohit", 100, 3}; // Much simpler initialization
// cout<<p.health<<endl; // Not "within the class"
// cout<<p.xp<<endl; // Not "within the class"
// cout<<p.name<<endl; // Not "within the class"
std::cout << p; // Simpler way to print
auto hero =
std::make_unique<player>("Tavishi", 1000, 3); // Smart pointer
// no need to delete
std::cout << *hero;
return 0;
}
I'm still learning how the abstract classes work and I want know if I'm on the right track or not.
This is my simplified program :
class CPerson
{
public:
CPerson() = default;
virtual int getMat() = 0;
};
class CStudent : public CPerson
{
public:
CStudent() = default;
CStudent(int MatriculationNr) { this->MatriculationNr = MatriculationNr;}
int getMat() { return MatriculationNr;}
private:
int MatriculationNr;
};
class CTeacher : public CPerson
{
public:
CTeacher() = default;
int getMat(){ return 0;}
private:
std::string name;
};
int main()
{
std::vector<CPerson*> test;
test.push_back(new CStudent(9898));
CTeacher *a = new CTeacher();
return 0;
}
In class CTeacher, I don't have the same private variable like CStudent (MatriculationNr) so I returned 0. The program is working normally. But is what I'm doing here correct or not?
Another question related to the abstract classes : Assuming we use virtual int& getMat() = 0; (with a reference), what should we return in CTeacher class? 0 will not work in this case, right?
Should we initalize a variable with 0 so that we can return it in this function, or is there a better implementation?
Below code sample should answer your question in a rather modern C++ way.
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// I have added a `std::string name` to the CPerson class and
// a `std::string subject` to the CTeachers class
// so both derived classes, CStudent and CTeacher have a name
// of the person involved and each derived class has
// something only it needs, MatrikulationNr for CStudent and
// Subject of teaching for CTeacher in order to deliver a more
// complete and more clearifying answer.
class CPerson {
int dummyMatriculationNr{ 0 };
std::string dummySubject{ "noTeacher" };
protected:
std::string name;
public:
std::string getName() { return name; }
virtual int& getMat() { return dummyMatriculationNr; }
virtual std::string getSubject() { return dummySubject; }
};
class CStudent : public CPerson {
int MatriculationNr{ 0 };
public:
CStudent() = delete; // we dont want anyone using this constructor
explicit CStudent(std::string name, int MatriculationNr) :
MatriculationNr{ MatriculationNr } {
this->name = name;
}
int& getMat() { return MatriculationNr; }
};
class CTeacher : public CPerson {
std::string subject{ "" }; // Subject of teaching
public:
CTeacher() = delete;
explicit CTeacher(std::string name, std::string subject) :
subject{ subject } {
this->name = name;
}
std::string getSubject() { return subject; }
};
int main() {
std::vector<std::unique_ptr<CPerson>> vp;
vp.push_back(std::make_unique<CStudent>("aStudentsName", 8989 ));// or emplace_back
vp.push_back(std::make_unique<CTeacher>("aTeachersName", "mathematics"));
for (auto& e : vp)
std::cout << "Name: " << e->getName() << " MatrNo: " << e->getMat()
<< " TeachingSubject: " << e->getSubject() << std::endl;
}
I hope above sample answers your question. However, using the keyword virtual creates a virtual function table, often called vtable, at runtime which costs performance and is considered not to be high performance computing anymore.
Its also confusing to have a getMat() function available in all derived classes when you need it only in one, the CStudents derived class. Although meaningless in any other class, this function still returns some dummy value there. That can be irritating. Same for the getSubject() function in CTeacher. See the output:
Name: aStudentsName MatrNo: 8989 TeachingSubject: noTeacher
Name: aTeachersName MatrNo: 0 TeachingSubject: mathematics
Consider to solve your question without any keyword virtual and having getMat() and int MatriculationNr in CStudents only and not in the base class at all. I know it is tempting to use virtual but its something to rather avoid as long as possible. For example, MFC, Microsoft Foundation Classes, the maybe biggest class inheritance project ever written, did not use virtual at all!
Consider the following code as an example:
#include <iostream>
#include <string>
#include <vector>
#include <variant>
// a code version without virtual
class CPerson {
protected:
std::string name;
public:
std::string getName() { return name; }
};
class CStudent : public CPerson {
int MatriculationNr{ 0 };
public:
CStudent() = delete; // we dont want anyone using this constructor
explicit CStudent(std::string name, int MatriculationNr) : MatriculationNr{ MatriculationNr } {
this->name = name;
}
int& getMat() { return MatriculationNr; }
};
class CTeacher : public CPerson {
std::string subject{ "" }; // Subject of teaching
public:
CTeacher() = delete;
explicit CTeacher(std::string name, std::string subject) : subject{ subject } {
this->name = name;
}
std::string getSubject() { return subject; }
};
int main() {
std::vector<CStudent> vs; // auto-deleted through RAII
std::vector<CTeacher> vt; // and good for serialisation and or database communication
vs.push_back(CStudent{ "aStudentsName", 9898 });
vt.push_back(CTeacher{ "aTeachersName", "mathematics" });
for (auto s : vs)
std::cout << s.getName() << " " << s.getMat() << std::endl;
for (auto t : vt)
std::cout << t.getName() << " " << t.getSubject() << std::endl << std::endl;
// and here we are done already,
// not listing the two different types in one vector
// but just using a vector for each derived class
//
// but lets try put them now into one vector
// using a more modern way through std::variant
// which keps all data in the vector and not only the
// CPerson part.
std::vector<std::variant<CStudent, CTeacher>> people;
// we could, for example, copy from above vectors
for (auto e : vs)
people.push_back(e);
for (auto e : vt)
people.push_back(e);
// we could insert new ones
people.push_back(CStudent { "aStudentsName1", 9899 });
people.push_back(CTeacher { "aTeachersName1", "physics" });
// and take that vector apart again
std::cout << std::endl << "Output from vector of variant:" << std::endl;
for (auto& e : people)
if (std::holds_alternative<CStudent>(e)) {
CStudent& s = std::get<CStudent>(e);
std::cout << s.getName() << " " << s.getMat() << std::endl;
}
else if (std::holds_alternative<CTeacher>(e)) {
CTeacher& s = std::get<CTeacher>(e);
std::cout << s.getName() << " " << s.getSubject() << std::endl;
}
}
There are numerous ways to achieve the goal to avoid virtual and I hope you did enjoy the above.
Everything in the code above seems alright. Just make sure to delete both objects after using them (the CStudent and the CTeacher).
I am learning object oriented programming.
To know which object is being destroyed, I want to add some code in the destructor of a class and use an attribute to do it.
For example-
class player{
public:
string name;
int health;
~player(){
cout<<name<<" destroyed";
}
};
In this example, name correctly helps me identify the object which is being destroyed.
But if there weren't any such attributes which could help me know which object was being destroyed, what should be done.
Is there a way to print the object's name itself. ( i.e. if I create a player enemy; then enemy is what I mean to say by name)
If you want it to be versatile, you can overload operator << instead of focusing solely on the destructor and outputting bits and pieces of your class attributes.
Here is an example:
#include <string>
#include <ostream>
#include <iostream>
class player {
std::string name;
int health;
public:
player(const std::string& n, int h) : name(n), health(h) {}
~player() { std::cout << "Destroying the following: " << *this << "\n"; }
friend std::ostream& operator << (std::ostream& os, const player& p);
};
std::ostream& operator << (std::ostream& os, const player& p)
{
os << p.name << " " << p.health;
return os;
}
int main()
{
player p1("Joe", 1);
player p2("Sam", 2);
std::cout << p1 << "\n" << p2 << "\n";
}
Output:
Joe 1
Sam 2
Destroying the following: Sam 2
Destroying the following: Joe 1
You can follow what was done by looking at some documentation here.
I'm writing some code to show inheritance.
In doing so, i want to illustrate it by having a base class that contains a vector of pointers that can hold object pointers of the derived class.
I'm getting this error that the "Child class is undeclared" in the base function "void addChild(string nm, string sm)" in the Parents class (base class). I do understand that it maybe out of scope in the base class.
Can someone provide me with a solution to this where i can still be able to instantiate an object of the derived class from within the base class.
I want to have everything done within the base class.
Please clarify if this is ok and is a good practice. If not, please suggest some ideas.
Here's my code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Parents // base class
{
vector <Parents*> fam;
protected:
string firstName;
string lastName;
public:
Parents()
{
//default constructor
}
Parents(string fn, string ln)
{
firstName = fn;
lastName = ln;
}
void displayChildren()
{
if (fam.empty())
{
cout << "Vector is empty" << endl;
}
else
{
for (unsigned int i = 0; i < fam.size(); i++)
{
std::cout, fam.at(i);
}
}
}
void displayParentsInfo(Parents& const par)
{
cout << "First name : " << par.firstName << endl;
cout << "Last name : " << par.lastName << endl;
}
void addChild(string nm, string sm)
{
Child* c1 = new Child(nm, sm);
fam.push_back(c1);
}
};
class Child : public Parents //derived class
{
string firstname;
string surname;
public:
Child()
{
//default constructor
}
Child(string a, string b)
{
firstname = a;
surname = b;
}
//~Child()
//{
//destructor called
//}
void displayChildInfo(Child & const c)
{
cout << "Child's firstname : " << c.firstname;
cout << "Child's surname : " << c.surname;
}
};
Cheers!
Just move the definition of the function out of the definition of the class:
class Parents // base class
{
...
void addChild(string nm, string sm);
};
class Child : public Parents //derived class
{
...
};
void Parents::addChild(string nm, string sm)
{
Parents* c1 = new Child(nm, sm);
fam.push_back(c1);
}
As for good practice, it might be better to have a non-member function that prepares the Child and returns a pointer to it, and add something like:
void Parents::addToFam(Parents* c1)
{
fam.push_back(c1);
}
I added all my code.
The exact problem I am facing is when I make the member variables private in the game.h file I get an error in the game.cpp file that says n p h are all private members of game.h. in Xcode.
But when I compile the program from the command line it compiles fine with no errors.
I am trying to understand if I am doing something wrong or is this up to standards the way I am doing this?
This is main.cpp
#include "game.h"
int main() {
game g("Female", "Magic", true, 21, 5, 120);
std::cout << "These are the things every game needs to be a game" << '\n';
std::cout << g << '\n';
return 0;
}
game.cpp
#include <iostream>
#include "game.h"
std::ostream& operator<<(std::ostream& s, const game& g) {
return s << &g.n << ' ' << &g.p << ' ' << &g.h;
}
This is my composite class
#include <iostream>
#include "npc.h"
#include "pc.h"
#include "health.h"
class game {
private:
npc n;
pc p;
health h;
public:
game(const npc& init_n, const pc& init_p, const health& init_h):
n(init_n),
p(init_p),
h(init_h)
{}
game(std::string gen, std::string abil, bool use, int lvl, int h, int arm) :
n(gen, abil),
p(use, lvl),
h(h, arm)
{
}
friend std::ostream& operator<<(std::ostream& s, const game& g) {
g.n.output(s);
g.p.output(s);
g.h.output(s);
return s;
}
npc get_n() { return n; }
pc get_p() { return p; }
health get_h() { return h; }
void set_n(npc init_n) { n = init_n; }
void set_p(pc init_p) { p = init_p ; }
void set_h(health init_h) { h = init_h; }
};
Here is a class
#include <iostream>
class health {
private:
int hp;
int armor;
public:
health(int init_hp, int init_armor) :
hp(init_hp),
armor(init_armor)
{
}
public:
void output(std::ostream& s) const { s << "Characters have this amount of hit points "<< hp << " and an armor rating of " << armor << "\n"; }
};
Here is a class
class pc {
private:
bool user;
int level;
public:
pc(bool init_user, int init_level) :
user(init_user),
level(init_level)
{
}
public:
void output(std::ostream& s) const { s << "A player character has at least "<< user << " user and a level of " << level << '\n'; }
};
Here is a class
#include <iostream>
class npc {
private:
std::string gender;
std::string ability;
public:
npc(std::string init_gender, std::string init_ability) :
gender(init_gender),
ability(init_ability)
{
}
public:
void output(std::ostream& s) const { s << "A non player character has a gender of "<< gender << " and an ability of " << ability << '\n'; }
};
You made several errors - a typo is the reason for your problem.
The function is not allowed to access those members because it is not a friend of the class.
The friend is (correctly) std::ostream& operator<<(std::ostream& s, const game& g)
while you defined a function std::ostream& operator<<(std::ostream& s, const game g), note the missing ampersand.
Also, your accessors should be const, and return a const reference.
Ie,
npc const& get_n() const { return n; }
pc const& get_p() const { return p; }
health const& get_h() const { return h; }
Your manipulators change the wrong variables! You change the ones passed to the function instead of the members of that class.... However, it is highly questionable that you add direct manipulators for the three private members. You must view your class as some abstract object and define operators that work on that object. If you just give direct access to all it's members than there is little left of the object orientation idea behind using a class with private members (this would still be ten times better than making them public though!)
Finally, just a coding style hint. It is common practice to use CamelCase names for custom classes (ie, class Game), and you're better of adding a prefix to your private members to distinguish them from function parameters. Often people use the prefix m_. You really should use complete english words too (not abbreviations, let alone single characters).
This would turn your code into, say...
class Game {
private:
Npc m_npc;
Pc m_pc;
Health m_health;
public:
Game(Npc const& npc, Pc const& pc, Health const& health) :
m_npc(npc), m_pc(pc), m_health(health) { }
etc.