C++ output all members in a object - c++

So far I have defined a simple class...
class person {
public:
string firstname;
string lastname;
string age;
string pstcode;
};
...then added some members and values to an object named "bill"...
int main() {
person bill;
bill.firstname = "Bill";
bill.lastname = "Smith";
bill.age = "24";
bill.pstcode = "OX29 8DJ";
}
But how would you simply output all those values? Would you use a for loop to iterate over each member?

I typically override operator <<, so that my objects are as easy to print as any built-in object.
Here is one way to override operator <<:
std::ostream& operator<<(std::ostream& os, const person& p)
{
return os << "("
<< p.lastname << ", "
<< p.firstname << ": "
<< p.age << ", "
<< p.pstcode
<< ")";
}
And then to use it:
std::cout << "Meet my friend, " << bill << "\n";
Here is a complete program using this technique:
#include <iostream>
#include <string>
class person {
public:
std::string firstname;
std::string lastname;
std::string age;
std::string pstcode;
friend std::ostream& operator<<(std::ostream& os, const person& p)
{
return os << "("
<< p.lastname << ", "
<< p.firstname << ": "
<< p.age << ", "
<< p.pstcode
<< ")";
}
};
int main() {
person bill;
bill.firstname = "Bill";
bill.lastname = "Smith";
bill.age = "24";
bill.pstcode = "OX29 8DJ";
std::cout << "Meet my friend, " << bill << "\n";
}

Simplistically, you output each element using an ostream:
class Person
{
public:
void Print_As_CSV(std::ostream& output)
{
output << firstname << ",";
output << lastname << ",";
output << age << ",";
output << pstcode << "\n";
}
string firstname;
string lastname;
string age;
string pstcode;
};
There may be different methods of printing, which is why I didn't overload operator <<. For example, one data member per line would be another popular scenario.
Edit 1: Why not looping?
The class has separate fields, which is why you can't iterate over the members.
If you want to iterator or loop over the members, you either have to have an iterator for your class or use a container, such as std::vector, that provides iteration.

Related

Making my own toString() method on c++ struct

I'm used to oveerriding the Java toString() method on my own objects in classes, but I'm not sure where I'm going wrong with the following code:
struct Student {
std::string name;
int age;
double finalGrade;
std::string toString() {
return "Name: " + name + "\n Age: " + age + "\n Final Grade: " + finalGrade;
}
};
I'm only beginning to learn c++ so any advice would be appreciated
In contrast to java, C++ does not offer a predefined "toString"-method that is called implicitly whenever a string representation of an object is requested. So your toString-method will have to be called explicitly then.
In C++, however, something similar is available by overriding the operator << for streams. Thereby, you can directly "send" the object contents to a stream (without the need to store everything in an intermediate string object). And you can use the same code to populate a string to be returned by a toStringmethod, too:
struct Student {
std::string name;
int age;
double finalGrade;
std::string toString() const;
};
ostream& operator << (ostream &os, const Student &s) {
return (os << "Name: " << s.name << "\n Age: " << s.age << "\n Final Grade: " << s.finalGrade << std::endl);
}
std::string Student::toString() const {
stringstream ss;
ss << (*this);
return ss.str();
}
int main() {
Student stud { "john baker", 25, 1.2 };
std::cout << "stud directly: " << stud << endl;
std::string studStr = stud.toString();
std::cout << "stud toString:" << studStr << endl;
}
You can't add anything you want to a std::string like you can to a Java String. Notably, most objects are not expected to have a toString member function. However, the standard library provides std::to_string which allow you to convert numeric values to an std::string. For example you could wrap the numeric values with a std::to_string to fix your function :
#include <string>
struct Student {
std::string name;
int age;
double finalGrade;
std::string toString() {
return "Name: " +
name +
"\n Age: " +
std::to_string(age) +
"\n Final Grade: " +
std::to_string(finalGrade);
}
};
Edit : Though this answer explains why what you tried doesn't work, the other answer's solution is the preferred approach.
You cant add int to std::string because the std::string operator+ was not overloaded to int.
The best solution is to use string stream :
#include <sstream>
std::string toString() {
std::ostringstream strout;
strout<< "Name: " << name << "\n Age: " << age << "\n Final Grade: " << finalGrade;
return strout.str();
}
You cannot just add an int or a double to an std::string. Use std::to_string to convert them first. This should work fine:
std::string toString() {
return "Name: " + name + "\n Age: " + std::to_string(age) + "\n Final Grade: " + std::to_string(finalGrade);
}

How do I go about printing a vector of objects?

I'm guessing I might have to use pointers, but haven't gone in depth too much on them in class yet to try and implement them in my program. I have this so far, the printing function is towards the middle of the program. I'm not quite sure on how to print out the elements from the vector as my approach didn't work.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class rolodex
{
string name;
string street, town, state;
string zip;
string phone;
vector <rolodex> entries;
public:
rolodex();
void getmenu();
void add_entry();
void set_name();
void set_address();
void set_phone();
void printinfo();
};
rolodex :: rolodex() : name(""), street(""), town(""), state(""), zip(""),
phone(""), entries()
{
}
void rolodex :: getmenu()
{
cout << "\n\n1)Add Entry";
cout << "\n5)Print All Entries";
cout << "\n6)Exit" << endl;
}
void rolodex :: add_entry()
{
rolodex temp;
cout << "\n\nEnter Name: ";
temp.set_name();
temp.set_address();
cout << "\n\nEnter Your Phone Number: ";
temp.set_phone();
entries.push_back(temp);
}
void rolodex :: set_name()
{
cin.ignore();
getline(cin, name);
}
void rolodex :: set_address()
{
cout << "\n\nNow we'll enter address information.";
cout << "\n\nStreet: ";
getline(cin, street);
cout << "\n\nTown: ";
getline(cin, town);
cout << "\n\nState: ";
getline(cin, state);
cout << "\n\nZip: ";
getline(cin, zip);
}
void rolodex :: set_phone()
{
getline(cin, phone);
}
void rolodex :: printinfo()
{
for(unsigned int i = 0; i < entries.size(); i++)
{
cout << entries[i] << endl; //This is where I'm stuck since I've only
//worked with vectors of non-object data
//type
}
}
int main()
{
rolodex person, menu;
short choice;
bool done = false;
do
{
menu.getmenu();
cout << "\n\nEnter a choice: ";
cin >> choice;
switch(choice)
{
case 1:
person.add_entry();
break;
case 5:
person.printinfo();
break;
case 6:
done = true;
break;
default:
cout << "\n\nInvalid Entry." << endl << endl;
}
} while(!done && isdigit(choice));
return 0;
}
πάντα ῥεῖ is right, but to add a little more detail...
You need to specify how you want the stream to handle your object. This is done by by adding a << operator. For example:
std::ostream& operator<<(std::ostream& s, const rolodex& r){
// Or however you want to format it.
s << "Name: " << r.name << " : ";
s << "Street: " << r.street << " : ";
s << "Town: " << r.town << " : ";
s << "State: " << r.state << " : ";
s << "Zip: " << r.zip << "\n";
}
Unfortunately, the function above tries to access the private fields of your class, which it can't because it is not part of the class definition.
An easy way to address that is to declare this function a "friend" inside of the class definition, like such:
friend std::ostream& operator<<(std::ostream&, const rolodex&);
...And since you might appreciate it, one big copy-pasteable chunk that you can use directly that should make your function work:
class rolodex
{
string name;
string street, town, state;
string zip;
string phone;
vector <rolodex> entries;
public:
rolodex();
void getmenu();
void add_entry();
void set_name();
void set_address();
void set_phone();
void printinfo();
friend std::ostream& operator<<(std::ostream&, const rolodex&);
};
std::ostream& operator<<(std::ostream& s, const rolodex& r){
// Or however you want to format it.
s << "Name: " << r.name << " : ";
s << "Street: " << r.street << " : ";
s << "Town: " << r.town << " : ";
s << "State: " << r.state << " : ";
s << "Zip: " << r.zip << "\n";
}
Following up on πάντα ῥεῖ's suggestion, here's one way of doing that, changing your design as little as possible:
1) Create a non-member overloaded operator<< for your rolodex class:
std::ostream& operator<< (std::ostream& os, const rolodex& rol)
{
os << rol.name << ":" << std::endl
<< "\t" << rol.street << std::endl
<< "\t" << rol.town << std::endl
<< "\t" << rol.state << std::endl
<< "\t" << rol.zip << std::endl
<< "\t" << rol.phone << std::endl;
return os;
}
.. but the compiler will chide you for attempting to access private members (by default, members are private) from outside the class, so you would have to relax the rules a bit:
class rolodex
{
...
public:
...
friend std::ostream& operator<< (std::ostream& os, const rolodex& rol);
};
You can't have the operator<< inside the class itself, see does-overloading-operator-works-inside-the-class.
However, it is almost always better design to add getter functions to your public interface anyway. You would have get_name() etc in the public: section of your class def, those functions would initially just return the values of the private member variables, and then your operator<< can use them instead of trying to access the private members. You then no longer require the friend declaration.
I upvoted Some programmer dude's remark about your design
The code for letting the use input the data really shouldn't be inside the rolodex class, because it makes the class hard to reuse. Image wanting to re-use the rolodex from a graphical interface, for example, and it's not such a good idea to have the rolodex contain instances of itself inside the vector.
I would suggest a
1) Person class containing all the person's attributes, with public getters get_name() and setters set_name() that don't use a specific entry method, just take the data as arguments e.g. set_name(std::string& name).
2) an non-member operator<< to output a person to an output stream
3) a Rolodex class with a private std::vector<Person> and methods to add a person, write all the persons to an output stream, etc..
Good luck & enjoy :-)
Edit: the menu structure on the terminal should IMHO be left inside the main() function or encapsulated into another class. But certainly don't leave it in Rolodex or worse, Person.

How to add a custom prefix in a << operator for a custom object

Is there a way to add a custom prefix in the operator<< for an object that I implement?
Ex:
class A {
public:
std::string id;
int count;
};
std::ostream &operator<<(std::ostream &os, const A &a)
{
os << os.prefix() << "Id: " << a.id << "\n";
os << os.prefix() << "Count: " << a.count << "\n";
return os;
}
If I do something like this:
A a;
a.id = "foo";
a.count = 1;
std::cout << a << std::endl;
The output will be:
Id: foo
Count: 1
I want to do something like:
std::cout << set_prefix(" -") << a << std::endl;
std::cout << set_prefix("==>") << a << std::endl;
To get an output like this:
-Id: foo
-Count: 1
==>Id: foo
==>Count: 1
A suggestion is to use std::setfill and os.fill, but std::setfill takes a single char as an argument and I need a custom string instead.
Solution
Looking at operator<<(std::basic_ostream) documentation, I found this:
Before insertion, first, all characters are widened using
os.widen(), then padding is determined as follows: if the number of
characters to insert is less than os.width(), then enough copies of
os.fill() are added to the character sequence to make its length
equal os.width(). If (out.flags()&std::ios_base::adjustfield) ==
std::ios_base::left, the fill characters are added at the end of the
output sequence, otherwise they are added before the output sequence.
After insertion, width(0) is called to cancel the effects of
std::setw, if any.
So the solution that works for me was save the original width of stream at the beggining and than recovering them when necessary.
std::ostream &operator<<(std::ostream &os, const A &a)
{
auto w = os.width();
os << std::setw(w) << "" << "Id: " << a.id << "\n";
os << std::setw(w) << "" << "Count: " << a.count;
return os;
}
Then:
std::cout << a << std::endl;
std::cout << std::setw(4) << a << std::endl;
std::cout << std::setfill('>') << std::setw(2) << a << std::endl;
Gave the following output:
Id: foo
Count: 1
Id: foo
Count: 1
>>Id: foo
>>Count: 1
Maybe a bit of overkill, but you can use something like this:
#include <iostream>
#include <sstream>
struct line_buffered_stream {
std::ostream& out;
std::stringstream ss;
std::string prefix;
line_buffered_stream(std::ostream& out,std::string prefix) :
out(out),prefix(prefix) {}
template <typename T>
auto operator<<(const T& t) -> decltype(this->ss << t,*this) {
ss << t;
return *this;
}
~line_buffered_stream(){
std::string line;
while (std::getline(ss,line)){
out << prefix << line << "\n";
}
}
};
int main() {
line_buffered_stream(std::cout,"==>") << "a\nb\n";
line_buffered_stream(std::cout,"-->") << "a\nb\n";
}
output:
==>a
==>b
-->a
-->b
Live Demo
Note that the implementation above is not meant to be used as anything else than a temporary whose lifetime is restricted to a single line of code. If you dont like that you'd have to add some mechanism to flush the stream to std::cout not to wait till the destructor is called.
I do not know of any way to do this with a string, but if you are content with just a char, it looks like you can use std::setfill manipulator, and than in your overload use the fill character:
std::cout << std::setfill('-') << a << std::endl;
std::ostream &operator<<(std::ostream &os, const A &a)
{
os << os.fill() << "Id: " << a.id << "\n";
os << os.fill() << "Count: " << a.count << "\n";
return os;
}
I'm not a big fan of this because it uses a global variable but that does allow you to have other classes use this same method, they just have to write thier own operator << correctly. It also requires that you call set_prefix(""); when you want to clear the prefix from printing. That said it does allow you to prepend any string you want to the output.
namespace details
{
// we neeed this for tag dispatch
struct Prefix {};
// this will be used in the class(es) operator << for the line prefix
std::string prefix;
// allows set_prefix to be called in the output stream by eating it return and returning the stream as is
std::ostream& operator <<(std::ostream& os, const Prefix& prefix)
{
return os;
}
}
// set the prefix and return a type that allows this to be placed in the output stream
details::Prefix set_prefix(const std::string& prefix)
{
details::prefix = prefix;
return {};
}
class A {
public:
std::string id;
int count;
};
std::ostream &operator<<(std::ostream &os, const A &a)
{
os << details::prefix << "Id: " << a.id << "\n";
os << details::prefix << "Count: " << a.count << "\n";
return os;
}
int main()
{
A a;
a.id = "foo";
a.count = 1;
std::cout << a << std::endl;
std::cout << set_prefix(" -") << a << std::endl;
std::cout << set_prefix("==>") << a << std::endl;
}
Output:
Id: foo
Count: 1
-Id: foo
-Count: 1
==>Id: foo
==>Count: 1
There is a way to store custom data on a stream object, but it isn't pretty: the iword and pword interfaces.
stream_prefix.hpp:
#ifndef STREAM_PREFIX_HPP_
#define STREAM_PREFIX_HPP_
#include <utility>
#include <string>
#include <ostream>
namespace stream_prefix_details {
class set_prefix_helper {
public:
explicit set_prefix_helper(std::string prefix)
: m_prefix(std::move(prefix)) {}
private:
std::string m_prefix;
// These insertion operators can be found by Argument-Dependent Lookup.
friend std::ostream& operator<<(
std::ostream&, set_prefix_helper&&);
friend std::ostream& operator<<(
std::ostream&, const set_prefix_helper&);
};
}
// The set_prefix manipulator. Can be used as (os << set_prefix(str)).
inline auto set_prefix(std::string prefix)
-> stream_prefix_details::set_prefix_helper
{ return stream_prefix_details::set_prefix_helper{ std::move(prefix) }; }
// Get the prefix previously stored by (os << set_prefix(str)), or
// an empty string if none was set.
const std::string& get_prefix(std::ostream&);
#endif
stream_prefix.cpp:
#include <stream_prefix.hpp>
namespace stream_prefix_details {
int pword_index() {
static const int index = std::ios_base::xalloc();
return index;
}
void stream_callback(std::ios_base::event evt_type,
std::ios_base& ios, int)
{
if (evt_type == std::ios_base::erase_event) {
// The stream is being destroyed, or is about to copy data
// from another stream. Destroy the prefix, if it has one.
void*& pword_ptr = ios.pword(pword_index());
if (pword_ptr) {
delete static_cast<std::string*>(pword_ptr);
pword_ptr = nullptr;
}
} else if (evt_type == std::ios_base::copyfmt_event) {
// The stream just copied data from another stream.
// Make sure we don't have two streams owning the same
// prefix string.
void*& pword_ptr = ios.pword(pword_index());
if (pword_ptr)
pword_ptr =
new std::string(*static_cast<std::string*>(pword_ptr));
}
// Can ignore imbue_event events.
}
std::ostream& operator<<(std::ostream& os,
set_prefix_helper&& prefix_helper)
{
void*& pword_ptr = os.pword(pword_index());
if (pword_ptr)
*static_cast<std::string*>(pword_ptr) =
std::move(prefix_helper.m_prefix);
else {
os.register_callback(stream_callback, 0);
pword_ptr = new std::string(std::move(prefix_helper.m_prefix));
}
return os;
}
std::ostream& operator<<(std::ostream& os,
const set_prefix_helper& prefix_helper)
{
void*& pword_ptr = os.pword(pword_index());
if (pword_ptr)
*static_cast<std::string*>(pword_ptr) = prefix_helper.m_prefix;
else {
os.register_callback(stream_callback, 0);
pword_ptr = new std::string(prefix_helper.m_prefix);
}
return os;
}
}
const std::string& get_prefix(std::ostream& os)
{
void* pword_ptr = os.pword(stream_prefix_details::pword_index());
if (pword_ptr)
return *static_cast<std::string*>(pword_ptr);
else {
// This string will never be destroyed, but it's just one object.
// This avoids the Static Destruction Order Fiasco.
static const std::string* const empty_str = new const std::string;
return *empty_str;
}
}
Usage:
#include <iostream>
#include <stream_prefix.hpp>
class A {
public:
std::string id;
int count;
};
std::ostream &operator<<(std::ostream &os, const A &a)
{
os << get_prefix(os) << "Id: " << a.id << "\n";
os << get_prefix(os) << "Count: " << a.count << "\n";
return os;
}
int main() {
A a;
a.id = "foo";
a.count = 1;
std::cout << a << std::endl;
std::cout << set_prefix("==> ") << a << std::endl;
}
Full working demo here.
Note this set_prefix manipulator is "sticky", meaning the setting will remain on the stream after use, like most of the standard manipulators except for std::setw. If you want it to reset after you're done outputting an A object description, just add os << set_prefix(std::string{}); to the operator<< function.
This works, but it is very, very ugly and terrible code.
Couple of issues:
- operator<< has to be defined outside of the class, because you want to take in class A as the rhs argument, instead of invoking it like A::operator<<() - and actually taking in a second A class as an argument.
- cout cannot deal with a void output, so because you insist on chaining setting the prefix with the cout commant, it has to return an empty string object.
- If you don't want the prefix to be remembered, just do prefix.clear() at the end of the operator<< definition.
class A
{
public:
std::string id;
std::string prefix;
int count;
std::string set_prefix(const std::string& inp)
{
prefix = inp;
return std::string();
}
std::string get_prefix() const
{
return prefix;
}
};
std::ostream &operator<<(std::ostream &os, const A &input)
{
os << input.get_prefix() << "Id: " << input.id << "\n";
os << input.get_prefix() << "Count: " << input.count << "\n";
return os;
}
int main()
{
A class1;
class1.id = "test";
class1.count = 5;
std::cout << class1.set_prefix(" -") << class1; // endl removed, as your operator<< definition already has a "\n" at the end.
std::cout << class1.set_prefix("==>") << class1;
}

C++ working with objects on heap

I am currently learning C++, coming from C#/Java background, using visual studio 2017.
I have a question in regards to creating objects on heap and referencing them properly down the road. So far I came across multiple tutorials and ways of doing things. Some recommend using smart pointers as much as possible, others swear its the devils tool.
My current main looks like this:
//Main
Person *makePerson()
{
string name;
int age;
cout << "Input name: ";
cin >> name;
cout << "Input age: ";
cin >> age;
return new Person(name, age);
}
Child *makeChild(Person &parent)
{
return new Child(*makePerson(), &parent);;
}
int main()
{
cout << "---Input parent data---" << endl;
Person *person = makePerson();
cout << "printing: " << *person << endl;
cout << "---Input child data---" << endl;
Child *child = makeChild(*person);
cout << "printing: " << *child << endl;
cout << "---end of main---" << endl;
delete person;
delete child;
return 0;
}
A function handles input of personal data and returns a pointer to new Person object. Then I have a function that handles creation of child object by taking a parent reference and asking makePerson for remaining data.
Can this be considered good C++? How can I make it better? I would really appreciate some code examples.
As some have already suggested, I could replace raw pointers with either shared_ptr<Person> person (heavy) or unique_ptr<Person> (better than shared).
This is code for Person and child classes. Note that Child has a raw pointer of type Person *parent.
//header
class Person
{
protected:
std::string name;
int age;
public:
Person();
Person(const Person& other);
Person(std::string inName, int inAge);
~Person();
virtual void print() const;
std::string getName() const;
int getAge() const;
Person &operator=(const Person &other);
//overload print functionality, act as if it was toString
friend std::ostream &operator<<(std::ostream &out, const Person &p);
};
//cpp
Person::Person() : name(""), age(0) {
std::cout << "Person empty constructor" << std::endl;
}
Person::Person(std::string inName, int inAge) : name(inName), age(inAge) {
std::cout << "Person (" << name << ") default constructor" << std::endl;
}
Person::Person(const Person & other) : name(other.name), age(other.age) {
std::cout << "Person (" << name << ") copy constructor" << std::endl;
}
Person::~Person() {
std::cout << "Person (" << name << ") destructor" << std::endl;
}
void Person::print() const {
std::cout << name << ", " << age << std::endl;
}
std::string Person::getName() const
{
return name;
}
int Person::getAge() const
{
return age;
}
Person & Person::operator=(const Person & other) {
std::cout << "Person (" << other.name << ") assignment constructor" << std::endl;
name = other.name;
age = other.age;
return *this;
}
std::ostream &operator<<(std::ostream &out, const Person &p) {
return out << p.name << ", " << p.age;
}
A child is a person and it makes sense for a child to have knowledge of who childs parent is. However, am uncertain how to handle this "knowledge". Here is code I am using for child class:
//Header
class Child : public Person
{
private:
const Person *parent;
public:
Child();
Child(std::string name, int age);
Child(std::string name, int age, const Person *parent);
Child(const Child &child, const Person *parent);
Child(const Person &person);
~Child();
Child &operator=(const Child &other);
void print() const;
friend std::ostream &operator<<(std::ostream &out, const Child &c);
};
//cpp
Child::Child() {
std::cout << "Child empty constructor" << std::endl;
}
Child::Child(std::string name, int age) : Person(name, age), parent(nullptr) {
std::cout << "Orphan (" << name << ") constructor" << std::endl;
}
Child::Child(std::string name, int age, const Person *parent) :
Person(name, age), parent(parent) {
std::cout << "Child (" << name << ") default constructor" << std::endl;
}
Child::Child(const Child &child, const Person *parent) :
Person(child.name, child.age), parent(parent) {
std::cout << "Child (" << child.name << ") copy constructor" << std::endl;
}
Child::Child(const Person &person) : Person(person), parent(nullptr) {
std::cout << "Child from person (" << name << ") constructor" << std::endl;
}
Child::~Child() {
std::cout << "Child (" << name << ") destructor" << std::endl;
}
Child & Child::operator=(const Child & other) {
name = other.name;
age = other.age;
parent = other.parent;
std::cout << "Child (" << name << ") assignment constructor" << std::endl;
return *this;
}
void Child::print() const {
if(parent)
std::cout << *this << " is child of " << *parent << std::endl;
else
std::cout << *this << " is orphan" << std::endl;
}
std::ostream &operator<<(std::ostream &out, const Child &c) {
return out << c.name << ", " << c.age << " is " <<
(c.parent ? ("child of " + c.parent->getName() + ", " + std::to_string(c.parent->getAge())) : "orphan");
}
This is the output I get:
I suppose my question still remains, could anyone give me an example of how it should look like to be considered good C++?
#user4581301 if you take a look at the updated main, do you mean I should return a std::unique_ptrinstead of a * (raw pointer)? In which case my function will look like this:
std::unique_ptr<Person> makePerson2()
{
string name;
int age;
cout << "Input name: ";
cin >> name;
cout << "Input age: ";
cin >> age;
return std::unique_ptr<Person>(new Person(name, age));
}
And variable declaration as:
std::unique_ptr<Person> upParent = makePerson2();
cout << "printing: " << *upParent << endl;
Would this be considered "better" C++ than what I have so far?
I think that one of the most important thing to know about C++ especially if you come from Java/C# background is:
Objects are value-types by default, not reference type!
you entire code could have been written as simply:
int main()
{
//this work
Person person("John Doe", 22);
//this work
Child child("Johnny Doe", 2, person);
cout << "---end of main---" << endl;
return 0;
}
See how the code turned into nothing? you don't have to worry about allocations, deleting unused object etc. because objects are not reference type to begin with!
My personal hierarchy of rules go:
use objects as value types as much as possible. pass them by reference to avoid copies. make sure a valid move constructor is implemented for relevant classes. objects as value types + references should be the default way of programming C++.
if you can't use a reference, because you want to specify a missing object, use C-pointer. by any way, strict the C-pointers to minimum and never let them manage anything. C-pointers are basically "viewers" to something and they can view "nothing" (or null). always think if you can replace C-pointer by C++ reference. if you can do it, do it.
use std::unique_ptr if for some reason you do need dynamic memory allocation, such as dynamic polymorphism. keep in mind that C++ works mostly on templates as static polymorphism, instead of the Java style inherit+override technique.
use std::shared_ptr rarely,and only when you're sure there are many owners, like an object which is referenced on different threads. std::shared_ptr should be used in extreme cases. always copy the shared pointer. never pass the shared pointer by reference.
Anyway, new , new[] , delete and delete[] are pretty much deprecated. only library writers should use them in very extreme cases. std::make_ should be the only way allocating object on the heap, alongside the STL containers such as std::vector and std::list.

Overloading operator <<

class Vehicle
{
public:
//[...]
virtual std::ostream& ostreamOutput(std::ostream&) const; // virtual in order to use it for subclasse like cars, busses etc.
virtual double Speed() const; //returns the speed of a vehicle, is implemented in derived classes
private:
int Number
std::string Name
//[...]
protected:
int MaxSpeed; //these variables were also needed in the derived classes
};
std::ostream& Vehicle::ostreamOutput(std::ostream& os) const
{
os << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::left) << std::setfill(' ') << ""
<< std::setw(4) << Number
<< std::setw(9) << Name
<< std::setw(15) << Speed()
<< std::setw(5) << MaxSpeed
return os;
}
std::ostream& operator<<(std::ostream& os, const Vehicle& x)
{
x.ostreamOutput(os);
return os;
}
main() //I wanted to overload the "<<"-Operator in order to print the vehicle information without //a seperate function
{
Vehicle Vehicle1("Vehicle1", 80);
std::cout << Vehicle1 << std::endl;//the first shift-operator contains the error
}
I tried to overload the Shiftoperator but I get the error named:
"error c2679 binary ' ' no operator found which takes a right-hand operand of type".
The error occured in the first Shift Operator in the main function. I want to print Vehicle and its derived classes with the overloaded operator.
Can you explain the error to me? I really do not know how to correct this.
I fixed all the typos (missed semicolons) in your source, and here is a complete working example:
#include <iostream>
#include <iomanip>
using namespace std;
class Vehicle
{
public:
//[...]
Vehicle (const char* Name, int Number)
: Name (Name), Number (Number)
{}
virtual std::ostream& ostreamOutput(std::ostream&) const; // virtual in order to use it for subclasse like cars, busses etc.
virtual double Speed() const {return 0.;} //returns the speed of a vehicle, is implemented in derived classes
private:
// remove in-class initializers below if you need to avoid C++11
int Number = -1;
std::string Name = "not set";
//[...]
protected:
int MaxSpeed = 200; //these variables were also needed in the derived classes
};
std::ostream& Vehicle::ostreamOutput(std::ostream& os) const
{
os << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::left) << std::setfill(' ') << ""
<< std::setw(4) << Number
<< std::setw(9) << Name
<< std::setw(15) << Speed()
<< std::setw(5) << MaxSpeed;
return os;
}
std::ostream& operator<<(std::ostream& os, const Vehicle& x)
{
x.ostreamOutput(os);
return os;
}
int main() //I wanted to overload the "<<"-Operator in order to print the vehicle information without //a seperate function
{
Vehicle Vehicle1("Vehicle1", 80);
std::cout << Vehicle1 << std::endl;//the first shift-operator contains the error
}
Maybe you output some other variables for which operator<< is not defined. To debug this case, split the code from e.g. this:
os << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::left) << std::setfill(' ') << ""
<< std::setw(4) << Number
<< std::setw(9) << Name
<< std::setw(15) << Speed()
<< std::setw(5) << MaxSpeed;
to this:
os << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::left) << std::setfill(' ') << ""
<< std::setw(4) << Number;
os << std::setw(9) << Name;
os << std::setw(15) << Speed();
os << std::setw(5) << MaxSpeed;
This way you'll get the error message for the real line that is causing trouble. Otherwise you'll get the error message only for the first line, the compiler you use apparently does not distinguish the lines in this case.
Your code example contains only typos (Vehicle <-> Fahrzeug, ostreamAusgabe <-> ostreamOutput, semicolon after Speed() in ostreamOutput()). Overloaded operator<< should work fine.
Try to compile and launch this code:
class Vehicle
{
public:
Vehicle(const std::string& name, int num)
: Name(Name)
, Number(num)
, MaxSpeed(100)
{}
virtual std::ostream& ostreamOutput(std::ostream&) const;
virtual double Speed() const;
private:
int Number;
std::string Name;
protected:
int MaxSpeed;
};
double Vehicle::Speed() const
{
return 0.0;
}
std::ostream& Vehicle::ostreamOutput(std::ostream& os) const
{
os << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::left) << std::setfill(' ') << ""
<< std::setw(4) << Number
<< std::setw(9) << Name
<< std::setw(15) << Speed()
<< std::setw(5) << MaxSpeed;
return os;
}
std::ostream& operator<<(std::ostream& os, const Vehicle& x)
{
x.ostreamOutput(os);
return os;
}
int main()
{
Vehicle Vehicle1("Vehicle1", 80);
std::cout << Vehicle1 << std::endl;
return 0;
}