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
Related
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...
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
}
I am fairly new to C++, although I do have some experience programming. I have built a Text class that uses a dynamic char* as it's main member. The class definition is below.
#include <iostream>
#include <cstring>
using namespace std;
class Text
{
public:
Text();
Text(const char*); // Type cast char* to Text obj
Text(const Text&); // Copy constructor
~Text();
// Overloaded operators
Text& operator=(const Text&);
Text operator+(const Text&) const; // Concat
bool operator==(const Text&) const;
char operator[](const size_t&) const; // Retrieve char at
friend ostream& operator<<(ostream&, const Text&);
void get_input(istream&); // User input
private:
int length;
char* str;
};
The issue I am having is I don't know how to use operator[] to assign a char value at the given index that's passed in. The current overloaded operator operator[] is being used to return the char at the index supplied. Anyone have experience with this?
I would like to be able to do something similar to:
int main()
{
Text example = "Batman";
example[2] = 'd';
cout << example << endl;
return 0;
}
Any help and/or advice is appreciated!
Solution provided - Thanks a bunch for all the replies
char& operator[](size_t&); works
You need to provide a reference to the character.
#include <iostream>
struct Foo {
char m_array[64];
char& operator[](size_t index) { return m_array[index]; }
char operator[](size_t index) const { return m_array[index]; }
};
int main() {
Foo foo;
foo[0] = 'H';
foo[1] = 'i';
foo[2] = 0;
std::cout << foo[0] << ", " << foo.m_array << '\n';
return 0;
}
http://ideone.com/srBurV
Note that size_t is unsigned, because negative indexes are never good.
This article is the definitive guide to operator overloading in C++ (which, to be honest, is mainly boilerplate code for syntactic sugar). It explains everything that is possible:
Operator overloading
Here's the portion that is of interest to you:
class X {
value_type& operator[](index_type idx);
const value_type& operator[](index_type idx) const;
// ...
};
And yes, this is possible, for the many of the STL containers (the vector for example), allow for array subscript notation to access data.
So you can do something along the lines of this:
char & operator[]( size_t i )
{
return *(str + i);
}
You should overload operator[] as non const method and return a reference from it
char& operator[](const int&);
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 ¤tNode)
{
// Output values here.
return output;
}
void Node::nodeFunction()
{
cout << *this;
}
Just as the title asks, does C++ have the equivalent of Python's setitem and getitem for classes?
Basically it allows you to do something like the following.
MyClass anObject;
anObject[0] = 1;
anObject[1] = "foo";
basically, you overload the subscript operator (operator[]), and it returns a reference (so it can be read as well as written to)
You can overload the [] operator, but it's not quite the same as a separate getitem/setitem method pair, in that you don't get to specify different handling for getting and setting.
But you can get close by returning a temporary object that overrides the assignment operator.
To expand on Earwicker post:
#include <string>
#include <iostream>
template <typename Type>
class Vector
{
public:
template <typename Element>
class ReferenceWrapper
{
public:
explicit ReferenceWrapper(Element& elem)
: elem_(elem)
{
}
// Similar to Python's __getitem__.
operator const Type&() const
{
return elem_;
}
// Similar to Python's __setitem__.
ReferenceWrapper& operator=(const Type& rhs)
{
elem_ = rhs;
return *this;
}
// Helper when Type is defined in another namespace.
friend std::ostream& operator<<(std::ostream& os, const ReferenceWrapper& rhs)
{
return os << rhs.operator const Type&();
}
private:
Element& elem_;
};
explicit Vector(size_t sz)
: vec_(sz)
{
}
ReferenceWrapper<const Type> operator[](size_t ix) const
{
return ReferenceWrapper<const Type>(vec_[ix]);
}
ReferenceWrapper<Type> operator[](size_t ix)
{
return ReferenceWrapper<Type>(vec_[ix]);
}
private:
std::vector<Type> vec_;
};
int main()
{
Vector<std::string> v(10);
std::cout << v[5] << "\n";
v[5] = "42";
std::cout << v[5] << "\n";
}
It's not portable, but MSVC has __declspec(property), which also allows indexers:
struct Foo
{
void SetFoo(int index, int value) { ... }
int GetFoo(int index) { ... }
__declspec(property(propget=GetFoo, propput=SetFoo)) int Foo[];
}
other than that, Earwicker did outline the portable solution, but he's right that you'll run into many problems.