Overloading the << operator and problems with add function - c++

So I recently got back into programming, in prep for my last year of physics and i'm having some trouble with an example.
It says I need to add the specific Exhibit class shown in the code, and then implement the functions. Then it wants me to display this as the output;
Max says Eeeeep
Jack says Roar
Petals says Woof
{ Max Jack Batty Sheepy Hippopotamusesy Turkey }
{ Max Jack Batty Sheepy Hippopotamusesy Turkey }
By overloading the << operator.
I've had a go, but im just stuck I believe i'm also doing the add() function incorrectly, so if someone could provide me with some insight it would be much appreciated.
Code:
#include <iostream>
#include <string>
using namespace std;
//------------------------------------------------------------
class Animal
{
private:
string name;
string sound;
public:
Animal(const string& n = "", const string& s = "");
~ Animal();
string getName() const {return name;}
string makeSound() const{return sound;}
};
Animal::Animal(const string&n, const string &s)
{
name=n;
sound=s;
}
Animal:: ~ Animal() //Destructor
{
}
ostream &operator <<(ostream& out, Animal & obj)
{
cout <<obj.getName()<<" says "<<obj.makeSound() ;
return out;
}
//------------------------------------------------------------
class Exhibit{
public:
Exhibit(int maxEnt = 10);
~Exhibit();
void add(const Animal& e);
Animal& operator [](size_t i){ return entries[i];};
friend ostream& operator <<(ostream& out, const Exhibit& obj);
private:
int MaxNumberOfAnimals;
int CurrentNumberOfAnimals;
Animal* entries;
};
Exhibit::Exhibit(int maxEnt)
{
MaxNumberOfAnimals=maxEnt;
}
Exhibit:: ~ Exhibit()
{
}
void add(const Animal& e)
{
int j=0;
entries[j]=e;
j++;
return;
}
ostream& operator <<(ostream& out, const Exhibit& obj)
{
cout <<"{ ";
for(int i=0;i++;i!=obj.MaxNumberOfAnimals)
{
cout << obj.entries[i] << ", ";
}
cout << "}"<<endl;
return out;
}
//------------------------------------------------------------
int main()
{
Animal* monkey = new Animal("Max", "Eeeeep");
Animal* tiger = new Animal("Jack", "Roar");
Animal* Dog = new Animal("Petals", "Woof");
cout << *monkey <<endl;
cout << *tiger <<endl;
cout << *Dog << endl;
Exhibit cage(10);
cage.add(*monkey);
cage.add(*tiger);
/*cage.add(Animal("Batty", "Screech"));
cage.add(Animal("Sheepy", "Bleat Bleat"));
cage.add(Animal("Hippopotamusesy", "growl"));
cage.add(Animal("Turkey","Gobble"));*/
cout << cage << endl;
cout << cage << endl;
delete monkey;
delete tiger;
delete Dog;
system("pause");
return 0;
}
//------------------------------------------------------------

One things that could be causing the problem with your << overloading is that you are sending everything to cout, rather than the out stream you pass in. A potential fix there could be changing "cout" to "out", as below:
ostream &operator <<(ostream& out, Animal & obj)
{
out <<obj.getName()<<" says "<<obj.makeSound() ;
return out;
}
As for your add function in your Exhibit class, it looks like you are initializing your counter 'j' each time you call the function, which means that it will always be 0. You can fix this by making your counter a private data member of the Exhibit class, or perhaps just by using your 'int CurrentNumberOfAnimals' to keep track, like below:
void add(const Animal& e)
{
entries[CurrentNumberOfAnimals]=e;
CurrentNumberOfAnimals++;
return;
}
There may be other errors in there that I didn't notice, but there are some.
Edit:
As posted in an above answer, entries is not initialized correctly. If you can, use a vector of Animals, like below:
#include <vector> //This should be in your Exhibit header file
class Exhibit{
public:
Exhibit(int maxEnt = 10);
~Exhibit();
void add(const Animal& e);
Animal& operator [](size_t i){ return entries[i];};
friend ostream& operator <<(ostream& out, const Exhibit& obj);
private:
int MaxNumberOfAnimals;
int CurrentNumberOfAnimals;
vector<Animal> entries;
};
This also simplifies your add function, though, see below:
void add(const Animal& e)
{
entries.push_back(e);
return;
}
2nd Edit:
So far as I can tell, this is how to do it using arrays. This is assuming that you need at most 10 animals in your "entries" array, since you have "int maxent = 10" in your original Exhibit class.
Your Exhibit class declaration could look like this (we shouldn't need the "int maxent" in your constructor anymore unless you need it for other reasons):
class Exhibit{
public:
Exhibit();
~Exhibit();
void add(const Animal& e);
Animal& operator [](size_t i){ return entries[i];};
friend ostream& operator <<(ostream& out, const Exhibit& obj);
private:
int MaxNumberOfAnimals;
int CurrentNumberOfAnimals;
Animal entries[10];
};
Your add function could then look like the first add function above, repasted here for convenience:
void add(const Animal& e)
{
entries[CurrentNumberOfAnimals]=e;
CurrentNumberOfAnimals++;
return;
}

entries[j] = e; - that's undefined behavior right there, because entries is uninitialized pointer (which results from junk data) and you're trying to access memory location which is pointed to by that invalid pointer.
If you can use std::vector, use it. Otherwise, your Exhibit class would need to partially implement one - allocation, deallocation, reallocation, deep copy if you want copyable Exhibit...

Related

Overloading the operator=? c++

I having a trouble trying to insert an object from a class that I created to a char. I create a class name Element as part of a bigger program, but when I try to overloading operator= so that i can get in char variable the char I got in the Element obj nothing work...
Element.h
class Element {
private:
char val;
public:
Element();
Element(char newVal); //check input - throw execption
~Element();
friend ostream& operator<<(ostream& os, const Element& obj);
void setElement(char newVal);
char getElement();
void operator= (const Element newVal);
void operator= (char newVal);
};
Element.cpp
#include "Element.h"
Element::Element()
{
val ='.';
}
Element::Element(char newVal)
{
if (newVal!='X' && newVal!='O'&& newVal!='.'){
inputExecption error;
error.what();
} else{
val=newVal;
}
}
Element::~Element()
{
}
void Element::setElement(char newVal)
{
if (newVal!='X' && newVal!='O'&& newVal!='.'){
inputExecption error;
error.what();
} else{
val=newVal;
}
}
char Element::getElement()
{
return val;
}
ostream& operator<<(ostream& os, const Element& obj)
{
return os << obj.val;
}
void Element::operator= (const Element Value){
val = Value.val;
}
void Element::operator= (char newVal){
if(val != 'X' && val != 'O'){
inputExecption a;
a.what();
}
val = newVal;
}
So as I said, what i'm trying to do is:
Element x='X';
char c = x; //(c=x.val)
cout<<c<<endl;//Will print X
thx! :)
In other words you're trying to convert an object of type Element to an object of type char. You can use a conversion operator for this:
class Element {
// ...
operator char() const { return val; }
};
The assignment operator only works when an instance of Element is used on the left hand side of the assignment.
IMHO, writing an implicit conversion operator (as 0x499602D2 suggested) is not the best idea.
For example, assume you have two separate file something like this:
//File char_utils.hh
#include <iostream>
void accept(char character) { std::cout <<"character: " <<character <<'\n'; }
//File elements_utils.hh
#include <iostream>
void accept(Element const& element) {
std::cout <<"element.getVal(): " <<element.getVal() <<'\n';
}
Then, depending on what you include in your implementation file (char_utils.hh or elements_utils.hh) you will get different behaviour, which may lead to many subtle bugs and/or interesting behaviours. ;)
This can be overcome by declaring conversion operator explicit, i.e.,
explicit operator char() const { return val; }
In such a case, you just need to:
Element e{'x'};
char c = static_cast<char>(e);
which shows the intent more clearly.
However, why do you need using an implicit conversion at all? Especially when you can use Element::getElement()? And if I may suggest, I would use different namin, e.g., Element::getValue(). Element::getElement() is very confusing.
Further reading: https://stackoverflow.com/a/16615725/1877420

Compare two objects in vector iteration C++

How to implement the comparison function in this case?
void remove(const Object1 &object1) {
for(auto &object2 : objectVector) {
if(object1 == object2) {
/*....... */
}
}
}
You are asking 2 questions:
How can objects be made comparable:
By implementing operator== for the class. Be sure you override operator != then too.
As a member function:
bool Object1::operator ==(const Object1 &b) const
{
// return true if *this equals b;
}
Or as a free function:
bool operator ==(const Object1 &a, const Object1 &b)
How can objects with a given value be removed from a vector:
The easiest way is to use std::remove:
objectVector.erase(std::remove(objectVector.begin(), objectVector.end(), object1), objectVector.end());
You can remove objects also while iterating through the vector, but you have to keep in mind that the vector iterator is invalidated then. You may not further iterate on the vector then.
An object of your class can contain different types and number of members so let's say that you have a class A:
class A{
int x,
float y;
char* z;
};
And you have two instances:
A a1;
A a2;
To compare:
if(a1 == a2) // compile-time error
;// DoSomeThing
Above you get the error because the compiler doesn't know which fields will be compared against each other. The solution is to overload the equals operator "==" to work on objects of your class.
class Student{
public:
Student(std::string, int age);
std::string getName()const;
int getAge()const;
bool operator == (const Student&);
private:
std::string name;
int age;
};
Student::Student(std::string str, int x) :
name(str), age(x){
}
bool Student::operator == (const Student& rhs){
return age == rhs.age;
}
std::string Student::getName()const{
return name;
}
int Student::getAge()const{
return age;
}
int main(){
Student a("Alpha", 77);
Student b("Beta", 49);
if(a == b)
std::cout << a.getName() << " is the same age as " <<
b.getName() << std::endl;
cout << endl << endl;
return 0;
}
Now the compiler knows how to compare objects of your class and know what the equals operator compares on your ojects members.
if object is a class you can override the operator == in the class as a friend function, or you can implement your own function bool isEqual(Object1 o1, Object1 o2) { if(something) return true; return false; }

Overloading << error

I am kind of newbie to programming migrated from legacy turbo c++ to VS C++2012,I have a tough time catching up and i wanted to emulate the string library for TC. But i cant make the insertion operator work in this code....Please help Out. Could you tell the mistake i made in this code. And also why are we returning the object via reference for overloading.
#include<iostream>
#include<string>
namespace String
{
class string
{
char word[100];
int size;
public:
string()
{
size=0;
}
string(int sz)
{
size=sz;
}
string(char *Word)
{
strcpy(word,Word);
size=sizeof(*Word);
}
~string()
{
}
string &operator+(string Add)
{
strcat(word,Add.word);
return *this;
}
string &operator=(char *Word)
{
strcpy(word,Word);
return *this;
}
/*
ostream &operator<<(ostream &sout,string Show)
{
sout<<Show.word;
return sout;
}
*/
void Show()
{
std::cout<<word;
}
};
}
void main()
{
String::string A="ABCDEF";
String::string B="GHIJK";
String::string C;
C=A+B;
C.Show();
std::cin.ignore(2);
//std::cout<<C;
}
You should declare operator<< as a non-member function, because ostream will be taken as the 1st argument for operator<<, a user define type's member function can't satisfy it.
namespace String
{
class string
{
...
public:
ostream& put(ostream &sout) { sout << word; return sout; }
};
ostream& operator<<(ostream& sout, string Show) { return Show.put(sout); }
}
The output operator << has to be overloaded in the namespace, not the class itself if you want to be able to use it like so:
cout << my_class_object;
So, in the declaration of your class (string.h) add this line:
ostream &operator<<(ostream & sout,const string & Show);
And then in the definition file (string.cpp) in your namespace, not the class itself, ad this function:
ostream & operator<<( ostream & out, const bigint & data )
{
// the printing implementation
}

How do I make a class in C++ so that it acts like a native int class

I am learning C++, and learned that int-types are just premade classes. So I thought maybe i should try to create one.
What I want to do basically is a
normal class of int
int x;
x=7;
cout << x;
// Output is 7 on screen.
so similarly...
abc x;
x=7;
cout << x;
What would I put in
class abc{
\\ HERE!!!!!!
};
so I could do this
class SomeClass {
public:
int x;
SomeClass(int x) {
this->x = x;
}
};
int main(int argc, char *argv[]) {
SomeClass s = 5;
cout << s.x << "\n"; // 5
s = 17;
cout << s.x << "\n"; // 17
return 0;
}
But as you can see I have to use s.x to print the value - I just want to use 's'.
I am doing it as an experiment, I don't want to hear about how this method is good or bad, pointless or revolutionary, or can 't be done. I remember once I did it. But only by copying and pasting code that I didn't fully understand, and have even forgotten about.
and learned that int, types, are just premade classes
This is completely false. Still, you have complete control on how your class will behave in expressions, since you can overload (almost) any operator. What you are missing here is the usual operator<< overload that is invoked when you do:
cout<<s;
You can create it like this:
std::ostream & operator<<(std::ostream & os, const SomeClass & Right)
{
Os<<Right.x;
return Os;
}
For more information, see the FAQ about operator overloading.
the << and >> are basically function names. you need to define them for your class. same with the +, -, * and all the other operators. here is how:
http://courses.cms.caltech.edu/cs11/material/cpp/donnie/cpp-ops.html
You need to overload operator<< for your class, like so:
class abc
{
public:
abc(int x) : m_X(x) {}
private:
int m_X;
friend std::ostream& operator<<(std::ostream& stream, const abc& obj);
};
std::ostream& operator<<(std::ostream& os, const abc& obj)
{
return os << obj.m_X;
}
You don't have to friend your operator<< overload unless you want to access protected/private members.
You must define in your class abc cast operator to int and assignment operator from int, like in this template class:
template <class T>
class TypeWrapper {
public:
TypeWrapper(const T& value) : value(value) {}
TypeWrapper() {}
operator T() const { return value; }
TypeWrapper& operator (const T& value) { this->value = value; return *this; }
private:
T value;
};
int main() {
TypeWrapper<int> x;
x = 7;
cout << x << endl;
}
You want to overload the output operator:
std::ostream& operator<< (std::ostream& out, SomeClass const& value) {
// format value appropriately
return out;
}

Passing a node as an outstream operator

This prints an error message about qualifiers but don't really understand what that means and how to adjust the code for it to work? Anyways, thanks a lot for looking at the code.
Note: The ostream operator is friended in the Node class.
using namespace std;
ostream& operator(ostream& output, const Node* currentNode)
{
return output;
}
void Node::nodeFunction()
{
//This node has items attached to the 'this' statement. After
//the necessary functions, this is called to output the items.
cout << this;
}
Your overloaded stream operator declaration should be like this:
std::ostream& operator<<(std::ostream& os, const T& obj);
^^^^^^^^^^^^^
You should be returning a reference to object of std::ostream, the & is wrongly placed in your overloaded function prototype.
Have a look at the working sample here.
Adding the source code here, for completeness.
Note: I have taken class Node members as public for ease of demonstration.
#include<iostream>
using namespace std;
class Node
{
public:
int i;
int j;
void nodeFunction();
friend ostream& operator <<(ostream& output, const Node* currentNode);
};
ostream& operator<<(ostream& output, const Node* currentNode)
{
output<< currentNode->i;
output<< currentNode->j;
return output;
}
void Node::nodeFunction()
{
//This node has items attached to the 'this' statement. After
//the necessary functions, this is called to output the items.
cout << this;
}
int main()
{
Node obj;
obj.i = 10;
obj.j = 20;
obj.nodeFunction();
return 0;
}
The & on the return value of the operator is in the wrong place, and it's generally better to use references rather than pointers for ostream operators:
ostream& operator<<(ostream &output, const Node &currentNode)
{
// Output values here.
return output;
}
void Node::nodeFunction()
{
cout << *this;
}