istream overloading with 2nd argument being a double pointer? - c++

My question is what is the proper way to implement this, and how exactly would I make use of it?
The operator to be overloaded has the following prototype:
//Reads a variable from an input stream
//A variable should have a one-word name that does not start with a digit or minus sign
istream& operator>>(istream& in, Variable** v)
We are given a variable class along with an equation class. I think the goal of overloading the istream operator is to make things easier when creating an equation object from a string. You can find it below.
My attempt at implementing this is as follows:
istream& operator>>(istream& in, Variable** v)
{
string i;
in >> i;
if (isalpha(i[0]) && i[0] != '-')
*v = new Variable(i);
return in;
}
Variable Class:
class Variable : public Operand
{
private:
static unordered_map<string, int> vars;
string name;
public:
Variable(string);
virtual int getValue() const override;
void setValue(int);
};
Equation class:
class Equation
{
private:
Variable* var;
Operand* lhs;
operator_t op;
Operand* rhs;
public:
Equation(string);
int evaluate();
//Should also implement copy constructor and copy assignment (rule of three)
~Equation();
};

Related

Syntax and overloading copy constructor

I am new to the topic of overloading copy constructors and I just wanted someone to look at my code for my class and see if I am overloading my copy constructor correctly. It is only using a single string as user input. Also, do I need the '&' or not?
class TODO {
private:
string entry;
public:
List* listArray = nullptr;
int itemCount = 0, currInvItem = 0;
int maxLength = 22;
TODO() { entry = ""; };
TODO(const string& ent) { setEntry(ent); }; // Is this correct?
void setEntry(string ent) { entry = ent; };
string getEntry() const { return entry; };
void greeting();
void programMenu();
void newArray();
void getList();
void incList();
void delTask();
string timeID();
string SystemDate();
friend istream& operator >>(istream& in, TODO& inv);
friend ostream& operator <<(ostream& out, TODO& inv);
void componentTest();
void setTask(string a);
string getTask();
bool validTask(string a);
bool notEmpty(string e);
};
That's correct, but it's just a constructor of TODO taking a const reference to a string. You can test it here.
Passing const string& ent (by const reference) is not a bad idea. Another option would be to pass string ent (by value), and move that string when initializing entry, i.e. : entry{ std::move(ent) }. As here.
The class TODO has a default copy constructor. Check the line at the Insight window here (you'll have to click Play first).:
// inline TODO(const TODO &) noexcept(false) = default;
The default copy constructor would just copy the members, including the List pointer, but not the List elements (shallow copy). Notice both instances of TODO would be pointing to the same List elements, and any operation on them would affect both instances.
Should you want to implement a custom copy constructor, the syntax would be (see here):
TODO(const TODO& other) {
std::cout << "custom copy_ctor\n";
*this = other;
// Copy listArray elements
...
}

Operation with 2 friends constructor

I created two classes and a constructor in each. Type followed a new class and constructors friends functions of the classes before.
#include <iostream>
using namespace std;
class clsAtmosfericConditions;
class clsDensity{
float density;
public:
clsDensity(){}
clsDensity(float densidad){
density = densidad;
}
friend istream& operator >>(istream &i, clsDensity &e);
friend ostream& operator <<(ostream &o, const clsDensity &s);
};
istream& operator >>(istream &i, clsDensity &e){
char sign;
i >> e.density >> sign >> sign >> sign >> sign >> sign >> sign;
return i;
}
ostream& operator <<(ostream &o, const clsDensity &s){
o << s.density << " Kg/m^3";
return o;
}
class clsDynamicViscocity{
double dynamicViscocity;
public:
clsDynamicViscocity(){}
clsDynamicViscocity(double viscocidadDinamica){
dynamicViscocity = viscocidadDinamica;
}
friend istream& operator >>(istream &i, clsDynamicViscocity &e);
friend ostream& operator <<(ostream &o, const clsDynamicViscocity &s);
};
istream& operator >>(istream &i, clsDynamicViscocity &e){
char sign;
i >> e.dynamicViscocity >> sign >> sign >> sign >> sign >> sign;
return i;
}
ostream& operator <<(ostream &o, const clsDynamicViscocity &s){
o << s.dynamicViscocity << " N/m^2";
return o;
}
class clsAtmosfericConditions{
friend clsDynamicViscocity::clsDynamicViscocity(double viscocidadDinamica);
friend clsDensity::clsDensity(float densidad);
public:
float kinematicViscocity();
};
float kinematicViscocity(){
float kinematicViscocity;
kinematicViscocity = dynamicViscocity/density; //Here is where IDE gives me the error
return kinematicViscocity;
}
The IDE displays an error in the function: error: 'dynamicViscocity' undeclares (first use this function)
I checked on some websites and I see no need to pass values ​​by reference builder when you do the operation.
Couple of problems here.
dynamicViscocity is a member of class clsDynamicViscocity. kinematicViscocity is not a member of any class, but I suspect is is intended to be a member of clsAtmosfericConditions. Regardless, kinematicViscocity is not a member of clsDynamicViscocity, so in order to operate on dynamicViscocity, it needs an object of type clsDynamicViscocity to provide dynamicViscocity.
Second, the visibility (public, private, protected) of dynamicViscocity is not specified, so C++ defaults to the most restrictive, private. A private member cannot be seen except by the object and those the object has defined as friends.
So kinematicViscocity has no dynamicViscocity and even if it did, it cannot see dynamicViscocity.
Suggested solution
Change the definition of kinematicViscocity to
float clsAtmosfericConditions::kinematicViscocity(const clsDynamicViscocity & vis,
const clsDensity & den)
{
float kinematicViscocity;
kinematicViscocity = vis.getDynamicViscocity() / den.getDensity();
return kinematicViscocity;
}
to provide a clsDynamicViscocity to kinematicViscocity and add a getter function
double getDynamicViscocity() const
{
return dynamicViscocity;
}
to clsDynamicViscocity.
The same needs to be done to access density from clsDensity.
EDIT
Waaaait a second...
Finally figured out what you are trying to do here:
friend clsDynamicViscocity::clsDynamicViscocity(double viscocidadDinamica);
friend clsDensity::clsDensity(float densidad);
A class declares who they will allow to see and use their hidden internals. A class cannot declare who's hidden internals they can see. Think of it this way, Bob can be friends with Alice and show her his secrets, but Bob cannot force Alice to be his friend and show him her secrets. Alice has to make that decision herself.
What the above means is the two methods can can violate encapsulation and see the hidden internals of clsAtmosfericConditions. clsAtmosfericConditions cannot however see the internals of clsDynamicViscocity or clsDensity.
clsDynamicViscocity and clsDensity have to friend class clsAtmosfericConditions to allow clsAtmosfericConditions to see into them, not the other way around.
So
clsDensity()
{
friend class clsAtmosfericConditions;
...
}
and
clsDynamicViscocity()
{
friend class clsAtmosfericConditions;
...
}
Now change kinematicViscocity to look like this:
float clsAtmosfericConditions::kinematicViscocity(const clsDynamicViscocity & vis,
const clsDensity & den)
{
float kinematicViscocity;
kinematicViscocity = vis.dynamicViscocity / den.density;
return kinematicViscocity;
}
and you are golden.
The original solution with the getters is a better solution as it requires no friends whatsoever and is much less tightly coupled. The guts of clsDynamicViscocity and clsDensity can be radically changed without breaking clsAtmosfericConditions so long as the getter function prototypes remain the same and clsAtmosfericConditions is granted no more access to clsDynamicViscocity and clsDensity than is required to get data.

Overloading operator for programming exercise

I'm in a programming class and need overloading explained to me. Simple question so hopefully I'll get an answer pretty quick. My understanding is that overloading an operator allows it to be used on a class. If that is true, then how would I overload >> to work with a class? I'm working on a small program to test out this idea and i'll post it here
#include <iostream>
#include <cstdlib>
#include "data.h"
using namespace std;
int main()
{
data obj;
cout << "What is the Number?" << endl;
cin >> obj;
system("pause");
return 0;
}
class data
{
public:
data operator >> (int);
private:
};
This page tells you mostly everything you need to know about operator overloading.
In short, nearly every operator in C++ can be overloaded for user-defined types. Some operators, like +, -, or >> must be defined outside of a class since they are free-standing, whereas others like copy assignment (=), must be defined within.
For your case, overloading the >> operator can be done in the following manner:
istream& operator>>(istream& in, data& d){
// Code here
return in;
}
Where it says "Code here", place the code you need to read into the data object.
For example, let us pretend that we were reading into a Point object with an x coordinate and a y coordinate. It is formatted in the stream like so: "(x,y)". The operator overload might look like this:
istream& operator>>(istream& in, Point& p){
char c;
in >> c;
if(c != '('){
in.clear(ios_base::failbit);
return in;
}
in >> p.x >> c >> p.y >> c;
return in;
}
This is just an example with minimal format checking, but hopefully it is enough to get you started.
Note that if members in your class are private, then you should friend the istream operator in the class definition:
class data{
...
public:
friend istream& operator>>(istream&, data&);
}
case1: no need to access private data
data.h.
class data {
public:
int i;
};
std::ostream& operator>> (std::istream&, data&); // better make operator >>
// a nonmember function
// if it doesn't need access
// to private data
data.cpp
#include "data.h"
std::istream& operator>> (std::istream& is, data& d) {
is>>d.i; // here we do some logic, we do what it means to do >> on
return is; // an instance of your data class and return reference to istream
}
case2: there is a need to access private data
data.h.
class data {
private:
int i;
friend std::ostream& operator>> (std::istream&, data&);
};
data.cpp
#include "data.h"
std::istream& operator>> (std::istream& is, data& d) {
is>>d.i; // here we do some logic, we do what it means to do >> on
return is; // an instance of your data class and return reference to istream
}
If you want to bolster your understanding of what operator overloading is, consider that essentially all operators on objects (such as "+", "++", "==", "!=", etc) are member functions.
Challenge yourself to recognize Obj a, b; a = b; as Obj a; Obj b; a.operator=(b);.
Overloading is purely providing a non-default implementation.
Here is a [terrible] overload of the cast-to-const-char* operator:
class BadWolf {
const char* m_text;
public:
BadWolf(const char* text) : m_text(text) {}
// if you really want the original text and ask for it with this function...
const char* tardisTranslation() const { return m_text; }
// but if you try to use me as a const char*...
operator const char* () const { return "bad wolf"; }
};
int main(int argc, const char* argv[]) {
BadWolf message("hello, sweetie");
std::cout << "Message reads: " << (const char*)message << std::endl;
std::cout << "Tardis translation: " << message.tardisTranslaction() << std::endl;
return 0;
}
I think this is what you want.
class data
{
friend istream& operator>>( istream&, data& );
private:
int data;
};
istream& operator>>( istream& in, data& d )
{
return in >> d.data;
}

Overloaded '+' Operator Not Compiling

I'm trying to understand the concept of operator overloading by writing some simple, silly tests. I thought this might be useful as this helps me understand C++ better.
Why does this example implementing a concatenation operator of Animal class and std::string not compile? G++ gives me the following error:
extra qualification 'Animal::' on member 'operator+' [-fpermissive]
This is the code:
#include <iostream>
using namespace std;
class Animal {
public:
string _type;
string _name;
string _sound;
Animal & Animal::operator+(const string & o);
};
Animal & Animal::operator+(const string & o) {
cout << "plus operator \n";
this->_name=o;
return *this;
}
int main( int argc, char ** argv ) {
Animal a;
a+"hhh";
cout<<a._name;
return 0;
}
Animal & Animal::operator+(const string & o);
Is invalid. It should be:
Animal & operator+(const string & o);
Also, your implementation of a simple addition operator, results in the modifications of one of the operands. This is never a good thing for an addition operator.
For example:
int a, b = 5, c = 3;
a = b + c;
That doesn't change the values of either operands; it leaves b and c untouched, and returns an entirely different instance.
You should therefore not overload the addition operator, but the addition assignment compound operator (+=):
Animal & operator+=(const string & o);
And of course change the implementation and calls to it accordingly:
Animal & Animal::operator+=(const string & o) {
cout << "plus operator \n";
this->_name=o;
return *this;
}
And:
a += "hhh";
The declaration of operator+ inside your class does not need to be qualified, precisely because it is being declared within the class:
class Animal {
// ...
Animal& operator+(const string& o);
}
This qualification is necessary when you define the function because you define it outside the class - the compiler needs to know to which class the function belongs.
There's no need for the Animal:: in the prototype, because it's inside the Animal class already. Just use:
Animal & operator+(const string & o);
The Animal:: qualification should be used in the definition of a member function, not in the declaration. Thus, change your operator declaration into:
Animal & operator+(const string & o);

Operator overloading >>

I am very new to C++ operator overloading and having some teething trouble.
I have defined:
void Graph::operator>>(const char* param)
The above function had to accept a string as input and then perform certain actions on the string. How do I call this function ? In what ways can I use it?
If you want to define operator so that you can do:
cin >> myGraph
cout << myGraph
You need to do something like this example below:
struct Entry
{
string symbol;
string original;
string currency;
Entry() {}
~Entry() {}
Entry(string& symbol, string& original, string& currency)
: symbol(symbol), original(original), currency(currency)
{}
Entry(const Entry& e)
: symbol(e.symbol), original(e.original), currency(e.currency)
{}
};
istream& operator>>(istream& is, Entry& en);
ostream& operator<<(ostream& os, const Entry& en);
Then implement operators:
istream& operator>>(istream& is, Entry& en)
{
is >> en.symbol;
is >> en.original;
is >> en.currency;
return is;
}
ostream& operator<<(ostream& os, const Entry& en)
{
os << en.symbol << " " << en.original << " " << en.currency;
return os;
}
Note: in this case the Entry is struct so it's members are public. If you don't want to make them public you can define the operator methods as friends so that they can access private members of Entry.
Here is how Entry would look like if it's members were not public:
struct Entry
{
private:
string symbol;
string original;
string currency;
public:
Entry() {}
~Entry() {}
Entry(string& symbol, string& original, string& currency)
: symbol(symbol), original(original), currency(currency)
{}
Entry(const Entry& e)
: symbol(e.symbol), original(e.original), currency(e.currency)
{}
friend istream& operator>>(istream& is, Entry& en);
friend ostream& operator<<(ostream& os, const Entry& en);
};
Graph myGraph;
myGraph >> "bla";
Note that yours is a weird use of operator>>(). Normally it's used like this:
NumericObject NumericObject::operator>>(NumericObject const& operand) const;
// bitshifts to the right
and
std::istream& operator>>(istream& in, StreamableObject& obj);
// parses a string representation of obj
I'm guessing what you are actually trying to do is be able to write code like this:
cin >> myGraph;
cout << myGraph;
Note that the graph object is not actually the object that gets its method called.
In this case, what you actually want to do is overload the global operator>> functions:
std::istream& operator>> (std::istream&, graph&);
std::ostream& operator<< (std::ostream&, const graph&);
If you're new to this, you picked a rather interesting (read as "not simple") problem to try to solve.
The operator overloads are not exactly functions. They are called indirectly when the compiler attempts to resolve code that looks something like this:
Graph g = new Graph();
g >> "do something";
I recommend you do NOT do this. Operator overloading can lead to VERY difficult bugs to troubleshoot, thanks to side effects. They are also hard on anyone who has to maintain your code (which might be you after you forgot why you did this).
Use operator overloads only when the meaning and use of them is intuitive.