Please explain to me why this is not detecting the << operator.
I tried my best, even tried to overload << on both classes (which is not necessary).
#include<iostream>
using namespace std;
const int MAX = 10;
class Complex;
template<class t>
class stack {
private:
t stk[MAX];
int top;
public:
stack() { top = -1; }
void push(t data) {
if (top == MAX - 1)
cout << "Stack is full.";
else
stk[++top] = data;
}
t pop() {
if (top == -1) {
cout << "Stack is empty.";
return NULL;
}
else {
//return stk[top--];
t data = stk[top];
top--;
return data;
}
}
};
class Complex {
private:
float real, imag;
public:
Complex(float r = 0.0, float i = 0.0) { real = r; imag = i; }
friend ostream& operator << (ostream& s, Complex& c);
};
ostream& operator << (ostream& s, Complex& c) {
s << "(" << c.real << "," << c.imag << ")";
return s;
}
int main() {
stack<int> s1;
s1.push(10);
s1.push(20);
s1.push(30);
s1.push(40);
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
stack<float> s2;
s2.push(3.14f);
s2.push(4.14f);
s2.push(5.14f);
s2.push(6.14f);
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
Complex c1(1.5f, 2.5f), c2(1.5f, 2.5f), c3(1.5f, 2.5f), c4(1.5f, 2.5f);
//cout<<c1;
stack<Complex> s3;
s3.push(c1);
s3.push(c2);
s3.push(c3);
s3.push(c4);
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
return 0;
}
The function signature should be something like:
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// write obj to stream
return os;
}
And the function pop can't return NULL since the type is not the same as t. Fixed code might like:
#include <iostream>
using namespace std;
const int MAX = 10;
class Complex;
template <class t>
class stack {
private:
t stk[MAX];
int top;
public:
stack() { top = -1; }
void push(t data) {
if (top == MAX - 1)
cout << "Stack is full.";
else
stk[++top] = data;
}
t pop() {
if (top == -1) {
cout << "Stack is empty.";
return {}; // May throw, or return std::optional here
} else {
// return stk[top--];
t data = stk[top];
top--;
return data;
}
}
};
class Complex {
private:
float real, imag;
public:
Complex(float r = 0.0, float i = 0.0) {
real = r;
imag = i;
}
friend ostream &operator<<(ostream &s, const Complex &c);
};
ostream &operator<<(ostream &s, const Complex &c) {
s << "(" << c.real << "," << c.imag << ")";
return s;
}
int main() {
stack<int> s1;
s1.push(10);
s1.push(20);
s1.push(30);
s1.push(40);
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
stack<float> s2;
s2.push(3.14f);
s2.push(4.14f);
s2.push(5.14f);
s2.push(6.14f);
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
Complex c1(1.5f, 2.5f), c2(1.5f, 2.5f), c3(1.5f, 2.5f), c4(1.5f, 2.5f);
// cout<<c1;
stack<Complex> s3;
s3.push(c1);
s3.push(c2);
s3.push(c3);
s3.push(c4);
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
return 0;
}
Online demo.
Related question: What are the basic rules and idioms for operator overloading?
It doesn't work because the second parameter should be a const reference
class Complex{
private:
float real,imag;
public:
Complex(float r=0.0,float i=0.0){
real=r;
imag=i;
}
friend ostream& operator<<(ostream& s, const Complex& c);
};
ostream& operator<<(ostream& s, const Complex& c) {
s<<"("<<c.real<<","<<c.imag<<")";
return s;
}
Reason:
The pop function returns an r-value. You can think of an r-value as a nameless object in memory (of course, there is more to it). You cannot put an r-value into an l-value reference. But for a const reference, it does not matter, since you are not going to modify it.
Solution 1:
friend ostream &operator<<(ostream &s, Complex &c); // accepts lvalue - c refers to some external Complex object.
friend ostream &operator<<(ostream &s, Complex &&c); // accepts rvalue - c becomes a normal local variable whose value is the passed rvalue.
Solution 2:
friend ostream &operator<<(ostream &s, const Complex &c); // accepts both
Related
i am trying to get these class template in C++ to work. But there is always this error.
there is some kind of error in overloading but i don't know what.
i have tried overloading << operator using member function but there is still error.
#include <iostream>
using namespace std;
const int MAX = 10;
template <class T>
class mstack
{
T stk[MAX];
int top;
public:
mstack()
{
top = -1;
}
void push(T data)
{
if(top==MAX-1)
{
cout << endl << "stack is full" << endl;
}
else
{
top++;
stk[top] = data;
}
}
T pop()
{
if (top==-1)
{
cout << endl << "stack is empty" << endl;
return NULL;
}
else
{
T data = stk[top];
top--;
return data;
}
}
};
class mcomplex
{
float img, real;
public:
mcomplex()
{
real = 0;
img = 0;
}
mcomplex(float r, float i)
{
real = r;
img = i;
}
friend ostream& operator<< (ostream &o,mcomplex &c);
};
ostream& operator<< (ostream &o, mcomplex &c)
{
o << c.real << "\t" << c.img;
return o;
}
int main()
{
mcomplex c1(1.5f,2.5f), c2(3.5f,4.5f), c3(-1.5f,-0.6f);
mstack <mcomplex> s3;
s3.push(c1);
s3.push(c2);
s3.push(c3);
cout << endl << (s3.pop());
cout << endl << s3.pop();
cout << endl << s3.pop() << endl;
return 0;
}
compiler error is as following:
|76|error: no match for 'operator<<' (operand types are
'std::basic_ostream::__ostream_type {aka
std::basic_ostream}' and 'mcomplex')
|62|note: candidate: std::ostream& operator<<(std::ostream&,
mcomplex&)
|77|error: invalid initialization of non-const reference of type
'mcomplex&' from an rvalue of type 'mcomplex'
|78|error: no match for 'operator<<' (operand types are
'std::basic_ostream::__ostream_type {aka
std::basic_ostream}' and 'mcomplex')
can anyone show what is the error here?
Your pop() function is returning a temporary value. Taking non-const reference to this value doesn't make sense.
Although it depends on your purpose, you should throw something exception like as follows, not T():
if (top==-1)
{
throw std::runtime_error("stack is empty");
}
Demo
Got this thing to finally work.
corrections were.
ostream& operator<< (ostream &o,const mcomplex &c)
{
o << c.real << "\t" << c.img;
return o;
}
and
if (top==-1)
{
cout << endl << "stack is empty" << endl;
return T();
}
I have the following class:
class Friend
{
public:
Friend();
~Friend(){}
void setName(string friendName){ name = friendName; }
void setAge(int friendAge) { age = friendAge; }
void setHeight(int friendHeight) { height = friendHeight; }
void printFriendInfo();
private:
string name;
int age;
float height;
};
//implementations
Friend::Friend()
{
age = 0;
height = 0.0;
}
//printing
void Friend::printFriendInfo()
{
cout << "Name : " << name << endl;
cout << "Age : " << age << endl;
cout << "Height : " << height << endl << endl;
}
And At this moment I can introduce the values in a vector, like this:
std::vector<Friend> regist(4, Friend());
regist[1].setAge(15);
regist[1].setHeight(90);
regist[1].setName("eieiei");
regist[2].setAge(40);
regist[2].setHeight(85);
regist[2].setName("random");
In debug, this solution works fine. But now I am trying to print the vector. So far without success.
for (int i = 0; i < regist.size(); i++) {
cout << regist[i]; //<-- error here
cout << '\n';
}
You might redesign a bit (in essence):
#include <iostream>
class Friend
{
public:
Friend();
// A more general name, const, and taking a stream.
void write(std::ostream&) const;
private:
std::string name;
int age;
float height;
};
Friend::Friend()
{
age = 0;
height = 0.0;
}
void Friend::write(std::ostream& stream) const
{
stream << "Name : " << name << std::endl;
stream << "Age : " << age << std::endl;
stream << "Height : " << height << std::endl << std::endl;
}
// Forward to the member function
inline std::ostream& operator << (std::ostream& stream, const Friend& object) {
object.write(stream);
return stream;
}
int main() {
Friend f;
std::cout << f;
}
Just call the printFriendInfo() member function:
for (int i = 0; i < regist.size(); i++) {
regist[i].printFriendInfo();
}
For
cout << regist[i];
to work, add a few accessor functions in Friend
string getName() const { return name; }
int getAge() const { return age; }
float getHeight() const { return height; }
and implement an overloaded operator<< function:
std::ostream& operator<<(std::ostream& out, Friend const& f)
{
out << "Name : " << f.getName() << std::endl;
out << "Age : " << f.getAge() << std::endl;
out << "Height : " << f.getHeight() << std::endl;
return out;
}
I get a linking error when i try to compile this code. I need to overload the output operator to display a three dimensional vector class I am not sure where to go from here any help is appreciated.
Vect3D.h
#ifndef VECT3D_H
#define VECT3D_H
#include <iostream>
class Vect3D
{
public:
Vect3D();
Vect3D(double xVal, double yVal, double zVal);
double getX() const { return x; }
double getY() const { return y; }
double getZ() const { return z; }
double magnitude() const { return sqrt(x*x + y*y + z*z); }
friend ostream& operator<<(ostream& os, const Vect3D& out);
void setX(double xVal) { x = xVal; }
void setY(double yVal) { y = yVal; }
void setZ(double zVal) { z = zVal; }
private:
double x;
double y;
double z;
};
ostream& operator<<(ostream& os, const Vect3D& out)
{
os << "(" << out.x << ", " << out.y << ", " << out.z << ")";
return os;
}
#endif
Vect3D.cpp
using namespace std;
#include "Vect3D.h"
Vect3D::Vect3D()
: x(0), y(0), z(0)
{ } // empty body
Vect3D::Vect3D(double xVal, double yVal, double zVal)
: x(xVal), y(yVal), z(zVal)
{ } // empty body
TestCode.cpp
#include <iostream>
#include <cmath>
#include <string>
#include <sstream>
using namespace std;
#include "Vect3D.h"
int main()
{
Vect3D v;
const Vect3D zero;
Vect3D v1(1, 2, 3), v2(7.5, 8.5, 9.5);
const Vect3D con(4, 5, 6);
cout << "Testing overload of << operator" << endl;
cout << v1;
cout << endl;
cout << "Should be:" << endl;
cout << "(" << v1.getX() << ", " << v1.getY() << ", " << v1.getZ() << ")" << endl << endl;
cout << "Testing chaining of overload of << operator" << endl;
cout << v1 << endl;
cout << "Should be:" << endl;
cout << "(" << v1.getX() << ", " << v1.getY() << ", " << v1.getZ() << ")" << endl << endl;
cout << "Testing overload of << operator for const Vect3D's" << endl;
cout << con << endl;
cout << "Should be:" << endl;
cout << "(" << con.getX() << ", " << con.getY() << ", " << con.getZ() << ")" << endl << endl;
cout << "Testing ostream parameter passing for the << operator" << endl;
stringstream sout;
sout << con;
string s = sout.str();
cout << s << endl;
cout << "Should be: " << endl;
cout << "(4, 5, 6)" << endl << endl;
cout << endl << endl;
return 0;
}
Errors:
Error 1 error LNK2005: "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream > &,class Vect3D const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABVVect3D###Z) already defined in TestCode.obj G:\overloadAssignment\overloadAssignment\Vect3D.obj
Error 2 error LNK1169: one or more multiply defined symbols found G:\overloadAssignment\Debug\overloadAssignment.exe 1
This directive has been used assiduously in other sections of this tutorial. When the preprocessor finds an #include directive it replaces it by the entire content of the specified header or file. See more information here.
So you have ostream& operator<<(ostream& os, const Vect3D& out) definition in Vect3D.h and you include this file in both TestCode.cpp and Vect3D.cpp. Thus you compile this function twice in Vect3D.obj and TestCode.obj. And when you try to link program, linker says that you have multiple definitions, and linker does not know what definition is right.
You need to put your implementation in Vect3D.cpp to compile it just once.
Vect3D.h
#ifndef VECT3D_H
#define VECT3D_H
#include <iostream>
class Vect3D
{
public:
Vect3D();
Vect3D(double xVal, double yVal, double zVal);
double getX() const { return x; }
double getY() const { return y; }
double getZ() const { return z; }
double magnitude() const { return sqrt(x*x + y*y + z*z); }
friend ostream& operator<<(ostream& os, const Vect3D& out);
void setX(double xVal) { x = xVal; }
void setY(double yVal) { y = yVal; }
void setZ(double zVal) { z = zVal; }
private:
double x;
double y;
double z;
};
ostream& operator<<(ostream& os, const Vect3D& out);
#endif
Vect3D.cpp
using namespace std;
#include "Vect3D.h"
Vect3D::Vect3D()
: x(0), y(0), z(0)
{ } // empty body
Vect3D::Vect3D(double xVal, double yVal, double zVal)
: x(xVal), y(yVal), z(zVal)
{ } // empty body
ostream& operator<<(ostream& os, const Vect3D& out)
{
os << "(" << out.x << ", " << out.y << ", " << out.z << ")";
return os;
}
I am doing a tutorial to learn about operator overloading and while writing the code as in the book, i got errors in the following section:
std::ostream &operator<<(std::ostream &outst, const AC_current &c)
{
outst << std::setiosflags(std::ios::fixed)<<std::setprecision(2);
outst << "(" << std::setw(6) << c.mag; //----->'mag' is a private member of 'AC_current'
outst << ", " << std::setw(6) << c.phase<<(char)248<< ") A"; //--->'phase' is a private member of 'AC_current'
return outst;
}
I defined it as a friend function, but its not working. What am I doing wrong?
P.S.This is the complete code.
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
const double Deg2Rad = 2*M_PI/360;
const double Rad2Deg = 360/(2*M_PI);
class AC_current
{
private:
double mag, phase;
double real, imag;
void setRect();
void setPolar();
public:
AC_current(double m=0, double p=0)
{
mag = m; phase = p; setRect();
}
AC_current operator-(const AC_current & c) const;
AC_current operator+(const AC_current & c) const;
AC_current operator*(double) const;
int getCoord();
friend std::istream &operator >> (std::istream &inst, AC_current &c);
friend std::ostream &operator << (std::ostream &outst, AC_current &c);
};
int AC_current::getCoord()
{
int selection;
do
{
std::cout << "\n Select: \n\t1) AC current in polar coordinates ";
std::cout << "\n\t2) AC current in rectangular coordinates ";
std::cout << "\n\t Enter selection: ";
std::cin >> selection;
} while ((selection!=1)&&(selection!=2));
return selection;
}
void AC_current::setRect()
{
real= mag*cos(phase*Deg2Rad);
imag=mag*sin(phase*Deg2Rad);
}
void AC_current::setPolar()
{
mag=sqrt(real*real+imag*imag);
if (!((real==0)&&(imag==0)))
{
phase=atan(imag/real)*Rad2Deg;
}
else
phase=0;
}
AC_current AC_current::operator-(const AC_current &c) const
{
AC_current temp;
double treal, timag;
treal = mag*cos(phase*Deg2Rad)-c.mag*cos(c.phase*Deg2Rad);
timag = mag*sin(phase*Deg2Rad)-c.mag*sin(c.phase*Deg2Rad);
temp.mag = sqrt(treal*treal+timag*timag);
if (!((treal==0)&&(timag==0)))
{
temp.phase = atan(timag/treal)*Rad2Deg;
}else temp.phase=0;
return temp;
}
AC_current AC_current::operator+(const AC_current &c) const
{
AC_current temp;
double treal, timag;
treal = mag*cos(phase*Deg2Rad)+c.mag*cos(c.phase*Deg2Rad);
timag = mag*sin(phase*Deg2Rad)+c.mag*sin(c.phase*Deg2Rad);
temp.mag = sqrt(treal*treal+timag*timag);
if (!((treal==0)&&(timag==0)))
{
temp.phase = atan(timag/treal)*Rad2Deg;
}else temp.phase=0;
return temp;
}
AC_current AC_current::operator*(double r) const
{
AC_current temp;
temp.mag = mag*r;
temp.phase = phase;
temp.setRect();
return temp;
}
std::istream &operator>>(std::istream &inst, AC_current &c)
{
int choice=c.getCoord();
if (choice==1)
{
std::cout << "\nEnter magnitude: ";
inst >> c.mag;
std::cout << "\nEnter phase shift: ";
inst >> c.phase;
c.setRect();
}
else if(choice == 2)
{
std::cout << "\nEnter real part: ";
inst >> c.real;
std::cout << "\nEnter imaginary part: ";
inst >> c.imag;
c.setPolar();
}
return inst;
}
std::ostream &operator<<(std::ostream &outst, const AC_current &c)
{
outst << std::setiosflags(std::ios::fixed)<<std::setprecision(2);
outst << "(" << std::setw(6) << c.mag;
outst << ", " << std::setw(6) << c.phase<<(char)248<< ") A";
return outst;
}
int menu()
{
int selection;
do
{
std::cout << "\n\n\tSelect operation:" << std::endl;
std::cout << "\n\n 1)Add currents" << std::endl;
std::cout << "\n\n 2)Substract currents" << std::endl;
std::cout << "\n\n 3)Multiply current by resistance" << std::endl;
std::cout << "\n\n 4)Exit" << std::endl;
std::cout << "\n\n Enter selection (1-4) => ";
std::cin >> selection ;
} while (selection<1||selection>4);
return selection;
}
int main ()
{
AC_current c1,c2;
int operation;
std::cin >> c1 >> c2;
while (operation !=4) {
operation = menu();
switch (operation) {
case 1:
std::cout << "\n\tc1+c2 = " << (c1+c2);
break;
case 2:
std::cout << "\n\tc1-c2 = " << (c1-c2);
break;
case 3:
double r;
std::cout <<"\nEnter resistance : ";
std::cin >> r;
std::cout << "\n\tc1*R = " << (c1*r);
break;
case 4:
break;
}
}
return 0;
}
I have a question about operators and how to overload them. There is an example of code and I'm overloading operator<< but it doesn't work. There is class that I use:
class CStudent{ //class for students and their attributes
int m_id;
int m_age;
float m_studyAverage;
public:
CStudent(int initId, int initAge, float initStudyAverage): m_id(initId), m_age(initAge), m_studyAverage(initStudyAverage){}
int changeId(int newId){
m_id = newId;
return m_id;
}
int increaseAge(){
m_age++;
return m_age;
}
float changeStudyAverage(float value){
m_studyAverage += value;
return m_studyAverage;
}
void printDetails(){
cout << m_id << endl;
cout << m_age << endl;
cout << m_studyAverage << endl;
}
friend ostream operator<< (ostream stream, const CStudent student);
};
Overload:
ostream operator<< (ostream stream, const CStudent student){
stream << student.m_id << endl;
stream << student.m_age << endl;
stream << student.m_studyAverage << endl;
return stream;
}
And there is main method:
int main(){
CStudent peter(1564212,20,1.1);
CStudent carl(154624,24,2.6);
cout << "Before the change" << endl;
peter.printDetails();
cout << carl;
peter.increaseAge();
peter.changeStudyAverage(0.3);
carl.changeId(221783);
carl.changeStudyAverage(-1.1);
cout << "After the change" << endl;
peter.printDetails();
cout << carl;
return 0;
}
Where is the problem?
The problem here is you need to learn what references are and the difference between std::ostream and std::ostream& is.
std::ostream& operator<< (std::ostream& stream, const CStudent& student)