Display List of Class in C++ - c++

Hello i'm new in programming and i'm trying to display a list of class in C++
i tried this :
#include <string>
#include <list>
class Person
{
public:
std::string Name;
Person();
virtual ~Person();
}
#include "Person.h"
#include <iostream>
#include <conio.h>
#include <list>
#include <string>
using namespace std;
int main()
{
Person p;
list<Person> lp;
p.Name= "Smith";
lp.push_back(p);
while (it != lp.end())
{
cout << *it;
it++;
}
_getch();
return 0;
}
but it display nothing, i don't know why ! can someone help me please ? thank you

Actually, the cout << *it; part is just fine.
What you've neglected to do is overload operator<< for your class. To assure consistency I'd probably change it to require a name when you create a Person, and then make Name a private member so outside code can't mess it up:
class Person
{
std::string Name;
public:
Person(std::string Name) : Name(Name) {}
virtual ~Person();
friend std::ostream &operator<<(std::ostream &os, Person const &p) {
return os << p.Name;
}
}
Then your code to create and print out a list could look something like this:
std::list<Person> people { "Smith", "Jones" };
for ( auto const &p : people)
std::cout << p << "\n";

If you want to print out the Person::Name field you would have to change your print statement
cout << *it;
to
cout << it->Name;
which will print out the name field in the Person instance.
Alternatively, you could overload operator << for you class, as described in #JerryCoffin's answer.

Related

Struggling with pointers to functions and references

I am working through this problem I found on Git to brush up on some skills. Using friend is prohibited. C++ styling should be used compared to C.
Essentially, I cannot call the identify() function that belongs to the Brain member variable in my Human class. It just will not let me access it. If you can code this up, and explain where I am going wrong, that would be great.
Create a Brain class, with whatever you think befits a brain. It will have an Identify() function that returns a string containing the brain's address in memory, in hex format, prefixed by 0x.
Then, make a Human class, that has a constant Brain attribute with the same lifetime. It has an identify() function, that just calls the identity() function of its Brain and returns its result.
Now, make it so this code compiles and displays two identical addresses:
int main(){
Human bob;
std::cout << bob.identify() << "\n";
std::cout << bob.getBrain().identify() << "\n";
}
Here is what I have so far:
#pragma once
#include "Brain.h"
class Human
{
const Brain humanBrain;
public:
Human();
std::string identify();
};
#include "Human.h"
#include <iostream>
#include <string>
#include <sstream>
Human::Human()
{
this->humanBrain = new Brain;
}
std::string Human::identify()
{
Brain b = this->humanBrain.identify(); // This is essentially what I am trying to call--and I can't access it.
const Brain * ptr = humanBrain;
std::ostringstream test;
test << ptr;
return test.str();
}
#pragma once
#include <string>
#include <iostream>
class Brain
{
int age;
std::string gender;
void* ptr;
public:
Brain();
//std::string getBrain();
const std::string identify();
void setPtr(void* p);
};
#include "Brain.h"
#include <iostream>
#include <sstream>
Brain::Brain()
{
age = 10;
gender = "male";
}
const std::string Brain::identify()
{
//const Brain* bPtr = &this;
const Brain* bPtr = this;
ptr = this;
std::ostringstream test;
test << &bPtr;
std::string output = "Brain Identify: 0x" + test.str();
return output;
}
Your Human::humanBrain member is declared as type const Brain, which is correct per the instructions, however your Brain::identify() method is not qualified as const, so you can't call it on any const Brain object. This is the root of the problem that you are having trouble with.
In addition, there are many other problems with your code, as well:
Human::humanBrain is not a pointer, so using new to construct it is wrong. And, you don't need a pointer to get the address of a variable anyway. Nor do you actually need a pointer to the member at all in this project.
Human lacks a getBrain() method, so bob.getBrain() in main() will not compile, per the instructions.
Human::identify() is calling humanBrain.identify(), which returns a std::string as it should, but is then assigning that string to a local Brain variable, which is wrong (not to mention, you are not even using that variable for anything afterwards). The instructions clearly state that Human::identity() should simply call Brain::identify() and return its result, but you are not doing that.
Brain::identify() is printing the address of its local variable bPtr rather than printing the address of the Brain object that identify() is begin called on, per the instructions.
With all of that said, try something more like this instead:
Human.h
#pragma once
#include "Brain.h"
#include <string>
class Human
{
const Brain humanBrain;
public:
Human() = default;
std::string identify() const;
const Brain& getBrain() const;
};
Human.cpp
#include "Human.h"
std::string Human::identify() const
{
return humanBrain.identity();
}
const Brain& Human::getBrain() const
{
return humanBrain;
}
Brain.h
#pragma once
#include <string>
class Brain
{
int age;
std::string gender;
public:
Brain();
std::string identify() const;
};
Brain.cpp
#include "Brain.h"
#include <sstream>
Brain::Brain()
{
age = 10;
gender = "male";
}
std::string Brain::identify() const
{
std::ostringstream test;
test << "Brain Identify: 0x" << this;
return test.str();
}

C++ class object default constructor bug

I am trying to create a class object s2 with some customized attributes and some attributes from default constructor however my output is the wrong output for the get_year function. It should be outputing 0 which is the key for FRESHMAN but it is out putting 2 instead. The rest of the code is outputting as expected:
#include <stdio.h>
#include <iostream>
#include <algorithm> // for std::find
#include <iterator> // for std::begin, std::end
#include <ctime>
#include <vector>
#include <cctype>
using namespace std;
enum year {FRESHMAN, SOPHOMORE, JUNIOR, SENIOR};
struct name
{
string firstName;
string lastName;
friend std::ostream& operator <<(ostream& os, const name& input)
{
os << input.firstName << ' ' << input.lastName << '\n';
return os;
}
};
class Student: name{
private:
name Name;
year Year;
int idNumber;
string Department;
public:
void setname(string fn="", string ln="")
{
Name.firstName =fn;
Name.lastName =ln;
}
name get_name()
{
return Name;
}
void set_year(year yr=FRESHMAN)
{
Year=yr;
}
year get_year()
{
return Year;
}
void set_ID(int ID=0)
{
idNumber=ID;
}
int get_ID()
{
return idNumber;
}
void set_Department(string Dept="")
{
Department=Dept;
}
string get_Department()
{
return Department;
}
};
int main()
{
Student s2;
s2.setname("Nikolai", "Khabeboolin");
s2.set_ID(12436193);
cout<<"ID is: "<< s2.get_ID()<<", name is "<< s2.get_name()<<", year in school is: "<<s2.get_year()<<", Department is "<<s2.get_Department()<<endl;
return 0;
}
Student lacks a constructor, so all its members are default initialized, and the default initialization of year Year and int idNumber is "no initialization", so reading from them is undefined behavior. Reading them might find 0, 2, a random value each time, or crash.
I see that your class contains a void set_year(year yr=FRESHMAN) member, but your code never called set_year, so no part of this executed.
You should make a default constructor for Student, or as Goswin von Brederlow stated, use year Year{FRESHMAN}; and int idNumber{-1}; when declaring the members, to give them default initializations.
By not explicitly declaring and defining a constructor, in this case Student(), you open yourself up to undefined behavior. Your constructor should call set_year(year yr=FRESHMAN) OR even better, just set the year itself.

Class contains no member named ... in C++

Assuming I am making a library of books in C++ this way:
#include <iostream>
#include <string>
#include <vector>
class Book
{
public:
Book(string name, string author)
};
Simple, just a constructor, now I create a vector of Book and push books back:
int main()
{
vector<Book> books;
books.push_back(Book("Gatsby", "Fitzgerald"));
But when I try to print out some member (name or author):
cout << books[0].name << endl;
return 0;
}
My boy compiler is angry:
error: ‘__gnu_cxx::__alloc_traits >::value_type {aka class Book}’ has no member named ‘name’
cout << books[0].name << endl;
I'm a relative beginner, does this approach make sense at all? And if it does, what did I do wrong?
Thank you!
The class Book has no members to store name and author. And, the constructor that you defined is syntactically wrong.
With public data members, it would look like this:
class Book
{
public:
// data members
std::string name;
std::string author;
// parameterized constructor
Book( std::string name, std::string author )
{
this->name = name;
this->author = author;
}
};
Please note that:
exposing data members like that is in violation of data-hiding principle of OOP. Ideally, the data members should be private and adequate accessor methods should be used.
the assignments of name and author in the body of the constructor is just for your understanding. If you've already studied the initializer list for constructor then use that.
Here's an example (live):
#include <iostream>
#include <string>
#include <vector>
class Book final
{
public:
// constructor with initializer list
Book( std::string name_, std::string author_ ) : name{name_}, author{author_} {}
// accessor methods
std::string getName() const { return name; }
std::string getAuthor() const { return author; }
private:
std::string name;
std::string author;
};
int main()
{
std::vector<Book> books;
books.push_back( Book{"The Alchemist", "Paulo Coehlo"} );
books.push_back( Book{"Fight Club", "Chuck Palahniuk"} );
books.push_back( Book{"No Country for Old Men", "Cormac McCarthy"} );
books.emplace_back( "Brave New World", "Aldous Huxley" );
books.emplace_back( "1984", "George Orwell" );
books.emplace_back( "Animal Farm", "George Orwell" );
for ( const auto& book : books )
{
std::cout << book.getName() << " by " << book.getAuthor() << '\n';
}
return 0;
}
Some relevant threads to read:
Why is "using namespace std;" considered bad practice?
push_back vs emplace_back
range-for loop
C++: "std::endl" vs "\n"

Adding inheritance in C++ multiple class file

I am learning C++ from the book called "Beginning C++ through Game Programming" and this problem showed up. The following code was originally 1 file, but I had to divide it into multiple classes.
Now, I am stuck at inheritance problem. I watched videos, read tutorials about it but nothing seemed to help. The book doesn't help either. I need to add the following attributes:
Use the multiple file class version (I am using it)
From a critter base class -- add at least 2 inheritance critters
The base class should have at least 2 attributes (data)
The inherited class should have at least 2 additional traits different from the base class and the other inherited class
Add the appropriate functions for all the attributes -- both base and inherited
Add appropriate menu items
Any help here would be highly appreciated!
critter.h
#pragma once
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Critter
{
public:
Critter(const string& name = "");
string GetName() const;
private:
string m_Name;
};
critterImp.cpp
#include <critter.h>
Critter::Critter(const string& name):
m_Name(name)
{}
inline string Critter::GetName() const
{
return m_Name;
}
farm.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Critter;
class Farm
{
public:
Farm(int spaces = 1);
void Add(const Critter& aCritter);
void RollCall() const;
private:
vector<Critter> m_Critters;
};
farmImp.cpp
#include <farm.h>
#include <critter.h>
Farm::Farm(int spaces)
{
m_Critters.reserve(spaces);
}
void Farm::Add(const Critter& aCritter)
{
m_Critters.push_back(aCritter);
}
void Farm::RollCall() const
{
for (vector<Critter>::const_iterator iter = m_Critters.begin();
iter != m_Critters.end();
++iter)
{
cout << iter->GetName() << " here.\n";
}
}
critFarmTest.cpp
#include <farm.h>
#include <critter.h>
int main()
{
Critter crit("Poochie");
cout << "My critter's name is " << crit.GetName() << endl;
cout << "\nCreating critter farm.\n";
Farm myFarm(3);
cout << "\nAdding three critters to the farm.\n";
myFarm.Add(Critter("Moe"));
myFarm.Add(Critter("Larry"));
myFarm.Add(Critter("Curly"));
cout << "\nCalling Roll...\n";
myFarm.RollCall();
return 0;
}

Weird behavior with OOP and string pointers

Here's my code:
#include <iostream>
#include <string>
class Human
{
public:
std::string * name = new std::string();
void introduce();
};
void Human::introduce()
{
std::cout << "Hello, my name is " << Human::name << std::endl;
}
int main()
{
Human * martha;
martha->name = new std::string("Martha");
martha->introduce();
return 0;
}
Well, it's supposed to print a message out like:
"Hello, my name is Martha" but it doesn't print neither the "Hello, my name is" string or the "Martha" name. Why does it occur?
The fix is simple and is to completely remove all pointers; see the code below. There are a number of issues with your code that I could address in detail, including memory leaks, uninitialized variables, and general misuse of pointers, but it seems that you're possibly coming from a different language background and should spend time learning good practice and the important semantics and idioms in modern C++ from a good C++ book.
#include <iostream>
#include <string>
class Human
{
public:
std::string name;
void introduce();
};
void Human::introduce()
{
std::cout << "Hello, my name is " << name << std::endl;
}
int main()
{
Human martha;
martha.name = "Martha";
martha.introduce();
return 0;
}
Few modifications are required to the code.
Updated code along with the comments to the change made are included below.
#include <iostream>
#include <string>
class Human
{
public:
//Removed pointer to a string
//Cannot have an instantiation inside class declaration
//std::string * name = new std::string();
//Instead have a string member variable
std::string name;
void introduce();
};
void Human::introduce()
{
//Human::name not required this is a member function
//of the same class
std::cout << "Hello, my name is " << name << std::endl;
}
int main()
{
Human *martha = new Human();
//Assign a constant string to string member variable
martha->name = "Martha";
martha->introduce();
return 0;
}
As suggested by #alter igel - The Definitive C++ Book Guide and List would be a good place to start.
#include <iostream>
#include <string>
class Human {
public:
void Human(std::string* n) { name = n; }
void introduce();
private:
std::string* name;
};
void Human::introduce() {
std::cout << "Hello, my name is " << name << std::endl;
}
int main() {
Human* martha = new Human(new std:string("Martha"));
martha->introduce();
return 0;
}
Try that. The difference is that you don't initialise the variable in the class definition, and you initialise the name with the constructor. You can split the method definition out into it's own section, but it's only one line and is fine being inside the class definition.