Update: I made Sergii's changes below, but now I get the error: undefined reference to `cs202::operator<<(std::basic_ostream >&, cs202::Rational const&)'. Any ideas how to fix this? Thanks
I would appreciate help figuring out why I am getting this error:
"error: 'output' is not a member of namespace 'cs202'"
I have a class called Rational as follows:
#ifndef RATIONAL_H
#define RATIONAL_H
namespace cs202{
class Rational
{
private:
int m_numerator;
int m_denominator;
public:
Rational(int nNumerator = 0, int nDenominator = 1) {
m_numerator = nNumerator;
m_denominator = nDenominator;
}
int getNumerator(){return m_numerator;}
int getDenominator(){return m_denominator;}
friend std::ostream& operator<<(std::ostream& output, const Rational& cRational);
};
}
#endif
The implementation file for the friend function which overrides the << operator looks like this:
#include "rational.h"
namespace cs202{
friend std::ostream& operator<<(std::ostream& output, const Rational& cRational)
{
output << cRational.m_numerator << "/" << cRational.m_denominator;
return output;
}
}
Finally, Main looks like this:
#include <iostream>
#include "rational.h"
using namespace std;
using namespace cs202;
int main()
{
Rational fraction1(1, 4);
cs202::output << fraction1 << endl;
return 0;
}
I have tried using cout instead of cs202:output, I have tried with and without the namespace cs202 (which is a requirement of the assignment), and I have tried making the operator overload function a member function of the class rather than a friend function to no avail.
What am I missing? Thanks
I suppose you want it out to standard output (to console)
int main()
{
Rational fraction1(1, 4);
std::cout << fraction1 << endl;
return 0;
}
Also you do not need friend here. "Friend" keyword is used only in a class
#include "rational.h"
namespace cs202{
std::ostream& operator<<(std::ostream& output, const Rational& cRational)
{
output << cRational.m_numerator << "/" << cRational.m_denominator;
return output;
}
}
Thanks, I figured it out. I had to change the placement of the {} for the namespace.
Related
I am fairly new to classes. I created a class called Counter which basically creates a counter object and has certain data members and function members associated with it.
The header file for the class is:
#ifndef c
#define c
#include <iostream>
#include <string>
#include <vector>
using std::vector; using std::string; using std::ostream;
class Counter{
int v_;
public:
vector<string> log_;
int initialized_;
Counter(int);
int value();
int get_v() const { return v_; } //getter
void set_v(int val) { v_ = val; } //setter
friend ostream & operator<<(ostream &, Counter &);
friend Counter operator+(const Counter &, const Counter &);
};
ostream & operator<<(ostream &, Counter &);
Counter operator+(const Counter &, const Counter &);
#endif
and the cpp implementation file looks like this:
#include "counter.h"
#include <iostream>
#include <vector>
#include <string>
using std::string; using std::vector; using std::ostream;
Counter::Counter(int a){
v_ = a;
initialized_ = a;
log_.push_back("Constructor called with a " + std::to_string(a));
}
int Counter::value(){
log_.push_back("value called. returned a " + std::to_string(v_));
return (v_--);
}
ostream & operator<<(ostream & out, Counter & c){
c.log_.push_back("<< called."); //line 1
out << "Counter("<< c.initialized_ << ")#" << c.v_; //line 2
return out;
}
Counter operator+(const Counter & c_one, const Counter & c_two){
Counter c_three(c_one.initialized_ + c_two.initialized_);
c_three.set_v(c_one.get_v()+c_two.get_v());
return c_three;
}
When I compile the file I get bombarded with expected primary-expression before ‘.’ token in line 1 and line 2 of the "<<" operator overloaded function. I really have no idea as to why this is happening. Any help?
What is c? You've defined it as nothing and then you use
c.log_.push_back(...)
Which the preprocessor changes to
.log_.push_back(...)
I'm not sure what you're trying to do but the error clearly states it's looking for an expression before the period, where it appears you have none.
Just got into C++ and I have a quick question.
After compiling with
g++ *.cpp -o output
I receive this error:
error: 'ostream' in 'class Dollar' does not name a type
These are my three files:
main.cpp
#include <iostream>
#include "Currency.h"
#include "Dollar.h"
using namespace std;
int main(void) {
Currency *cp = new Dollar;
// I want this to print "printed in Dollar in overloaded << operator"
cout << cp;
return 0;
}
Dollar.cpp
#include <iostream>
#include "Dollar.h"
using namespace std;
void Dollar::show() {
cout << "printed in Dollar";
}
ostream & operator << (ostream &out, const Dollar &d) {
out << "printed in Dollar in overloaded << operator";
}
Dollar.h
#include "Currency.h"
#ifndef DOLLAR_H
#define DOLLAR_H
class Dollar: public Currency {
public:
void show();
};
ostream & operator << (ostream &out, const Dollar &d);
#endif
Thank you for your time, and everything helps!
You have a number of errors in the code.
You heavily use using namespace std. This is a bad practice. In particular, this led to the error you faced: you don't have using namespace std in Dollar.h, thus the compiler has no idea what ostream means. Either put using namespace std in Dollar.h too, or better just stop using it and specify the std namespace directly, as in std::ostream.
You use std::ostream in your headers, but you don't include the corresponding standard library header <ostream> in them (<ostream> contains the definition of std::ostream class; for the full I/O library include <iostream>). A really good practice is to include all the dependencies of the header in the header itself, so that it is self-contained and can be safely included anywhere.
You are implementing a stream output operator with signature std::ostream & operator << (std::ostream &, Dollar const &), which is perfectly valid. However, you call it for a pointer to type Dollar. You should rather call it with the object itself, not the pointer, so you should dereference the pointer: std::cout << *cp;.
You implemented the output operator for the Dollar class, but use it for a variable of type Currency: this won't work. There is a way to do this - there do exist virtual methods for this exact reason. However, in this case the operator is a free function, thus it cannot be virtual. So, you should probably add a virtual print method to your Currency class, implement it in Dollar, and call it from output operator:
#include <iostream>
class Currency {
public:
virtual void print (std::ostream &) const = 0;
};
class Dollar : public Currency {
void print (std::ostream & out) const override {
out << "A dollar";
}
};
std::ostream & operator << (std::ostream & out, Currency const & c) {
c.print(out);
return out;
}
int main(/* void is redundant here */) {
Currency *cp = new Dollar;
std::cout << *cp;
// return 0 is redundant in main
}
You need to #include <iostream> within Dollar.h so that your std::ostream & operator is resolved by the compiler.
I get this when i try to compile:
../Monster.h:26:9: error: ‘int ProjectIV::Monster::con’ is private
`int con;`
^
../Monster.cpp:17:39: error: within this context
cout << "Constitution: " << monster.con << endl;
^
make: * [Monster.o] Error 1
From what I understand making operator<< a friend should allow it to access int con. What am I not seeing.
Monster.h:
#ifndef MONSTER_H_
#define MONSTER_H_
#include <iostream>
using std::cout;
using std::endl;
using std::ostream;
#include <string>
using std::string;
namespace ProjectIV
{
class Monster
{
friend ostream &operator<< (ostream &out, const Monster &monster);
public:
Monster(int con);
private:
int con;
};
} /* namespace ProjectIV */
#endif /* MONSTER_H_ */
Monster.cpp:
#include "Monster.h"
ostream &operator<< (ostream &out, const ProjectIV::Monster &monster)
{
cout << "Constitution: " << monster.con << endl;
return out;
}
ProjectIV::Monster::Monster(int con): con(con)
{}
main.cpp:
#include "Monster.h"
using namespace ProjectIV;
int main()
{
Monster Gojira(140);
cout << Gojira << endl;
return 0;
}
This:
ostream& operator<<(ostream& out, const ProjectIV::Monster& monster)
should be:
ostream& ProjectIV::operator<<(ostream& out, const ProjectIV::Monster& monster)
Here your not working example, and here is the working one.
Also, as per AndreyT's comment, you should add a function declaration before the friend declaration:
namespace ProjectIV {
class Monster {
friend ostream& operator<<(ostream& out, const Monster& monster);
public:
Monster(int con);
private:
int con;
};
ostream& operator<<(ostream& out, const Monster& monster);
// ^^^ this
}
There are two problems with your code.
Firstly, the friend declaration inside Monster class refers to ProjectIV::operator << function. It is ProjectIV::operator << that will become the friend of Monster. What you defined in your Monster.cpp file is actually a ::operator <<. This is a completely different function that is not a friend of Monster. This is why you get the error.
So, you need to decide what function you want to make a friend - the one in global namespace or the one in ProjectIV namespace - and act accordingly.
If you want to make your operator << a member of ProjectIV namespace, you run into the second problem. Friend declarations refer to member of enclosing namespace, but they don't introduce the corresponding declarations into the enclosing namespace. It is still your responsibility to add a declaration for operator << in ProjectIV
namespace ProjectIV
{
class Monster
{
friend ostream &operator<< (ostream &out, const Monster &monster);
public:
Monster(int con);
private:
int con;
};
ostream &operator<< (ostream &out, const Monster &monster);
} /* namespace ProjectIV */
and then later define it as a member of ProjectIV
ostream &ProjectIV::operator<< (ostream &out, const ProjectIV::Monster &monster)
{
cout << "Constitution: " << monster.con << endl;
return out;
}
I've looked up information for overloading the << operator, and it seems like I did everything correctly, but I keep getting a compile error. I've friended this function in my header file, and placed a prototype at the top of my cpp file.
My University.h:
#ifndef UNIVERSITY_H
#define UNIVERSITY_H
#include <string>
#include <vector>
#include <iostream>
using namespace std;
#include "Department.h"
#include "Student.h"
#include "Course.h"
#include "Faculty.h"
#include "Person.h"
class University
{
friend ostream& operator<< (ostream& os, const vector<Department>& D);
friend ostream& operator<< (ostream& os, const Department& department);
protected:
vector<Department> Departments;
vector<Student> Students;
vector<Course> Courses;
vector<Faculty> Faculties;
static bool failure;
static bool success;
public:
bool CreateNewDepartment(string dName, string dLocation, long dChairID);
bool ValidFaculty(long dChairID);
};
#endif
My University.cpp:
#ifndef UNIVERSITY_CPP
#define UNIVERSITY_CPP
#include<string>
#include<vector>
#include<iostream>
using namespace std;
#include "University.h"
ostream& operator<<(ostream& os, const vector<Department>& D);
ostream& operator<<(ostream& os, const Department& department);
bool University::failure = false;
bool University::success = true;
bool University::CreateNewDepartment(string dName, string dLocation, long dChairID)
{
if((dChairID != 0) && (ValidFaculty(dChairID)== University::failure))
{
Department D(dName, dLocation, dChairID);
Departments.push_back(D);
for (int i = 0; i < Departments.size(); i++)
cout << Departments;
return University::success;
}
return University::failure;
}
bool University::ValidFaculty(long dChairID)
{
for (int i = 0; i < Faculties.size(); i++)
{
if (Faculties[i].ID == dChairID)
return University::success;
}
return University::failure;
}
ostream& operator<<(ostream& os, const vector<Department>& D)
{
for (int i = 0; i < D.size(); i++)
os << D[i] << endl;
os << "\n";
return os;
}
ostream& operator<< (ostream& os, const Department& department)
{
department.Print(os);
return os;
}
#endif
My Department.h:
#ifndef DEPARTMENT_H
#define DEPARTMENT_H
#include<vector>
#include<string>
#include<iostream>
using namespace std;
class Department
{
friend class University;
friend ostream& operator<< (ostream& os, Department& department);
protected:
long ID;
string name;
string location;
long chairID;
static long nextDepartID;
public:
Department();
Department(string dName, string dLocation, long dChairID);
void Get();
void Print(ostream& os)const;
};
#endif
My Department.cpp:
#ifndef DEPARTMENT_CPP
#define DEPARTMENT_CPP
#include<iostream>
#include<string>
using namespace std;
#include "Department.h"
long Department::nextDepartID = 100;
Department::Department()
{
ID = nextDepartID++;
name = "Null";
location = "Null";
chairID = 0;
}
Department::Department(string dName, string dLocation, long dChairID):name(dName), location(dLocation), chairID(dChairID)
{
ID = nextDepartID++;
}
void Department::Get()
{
}
void Department::Print(ostream& os)const
{
os << "\n";
os << ID << endl;
os << name << endl;
os << location << endl;
os << chairID << endl;
os <<"\n\n";
}
ostream& operator<< (ostream& os, const Department& department)
{
department.Print(os);
return os;
}
#endif
Now everything can be seen that pertains only to this problem. The only error I receive now is that void value is not being ignored.
Snippet of error:
University.cpp: In function ‘std::ostream& operator<<(std::ostream&, const Department&)’:
University.cpp:53: error: void value not ignored as it ought to be
Department.cpp: In function ‘std::ostream& operator<<(std::ostream&, const Department&)’:
Department.cpp:42: error: void value not ignored as it ought to be
FINAL EDIT:
Thanks to everyone that helped me. I definitely have a better understanding of operator overloading now...especially when it deals with printing vectors of user-defined types!
The complaint was that while your function to iterate over and print the vector contents may have been correct, the actual object contained by the vector did not have an operator<< specified.
You need to have one.
If you already have a method called Print() in your Department class, you could simply create an overload for operator<< as follows:
std::ostream& operator<<(std::ostream& os, const Department& department) {
os<<department.Print();
return os;
}
I had prepared the following code before you posted your update. Maybe it can help you.
#include<iostream>
#include<vector>
#include<string>
class Department {
public:
Department(const std::string& name)
: m_name(name) { }
std::string name() const {
return m_name;
}
private:
std::string m_name;
};
// If you were to comment this function, you would receive the
// complaint that there is no operator<< defined.
std::ostream& operator<<(std::ostream& os, const Department& department) {
os<<"Department(\""<<department.name()<<"\")";
return os;
}
// This is a simple implementation of a method that will print the
// contents of a vector of arbitrary type (not only vectors, actually:
// any container that supports the range-based iteration): it requires
// C++11.
template<typename T>
void show(const T& container) {
for(const auto& item : container) {
std::cout<<item<<std::endl;
}
}
int main() {
std::vector<Department> deps = {{"Health"}, {"Defense"}, {"Education"}};
show(deps);
}
Compile with g++ example.cpp -std=c++11 -Wall -Wextra (I used OS X 10.7.4 and GCC 4.8.1) to get:
$ ./a.out
Department("Health")
Department("Defense")
Department("Education")
Lately, when I implement a class I create a nested namespace named operators where I add the stream operators.
I do this because I often need to use them in a namespace other than the class' namespace os I do a
using my_namespace::operators;
just where I want it and that's it.
Here I have an example with a class Point, a class Segment and their stream operators where the Segment's stream calls the Point's stream. But... I cannot compile:
Class Point:
#ifndef POINT_HPP
#define POINT_HPP
#include <iostream>
namespace geom {
class Point
{
public:
Point(int x_, int y_) : x(x_), y(y_) {};
int x;
int y;
};
namespace operators {
std::ostream& operator<<(std::ostream& out, const Point& p)
{
out << "(" << p.x << ", " << p.y << ")";
return out;
}
} // ~ namespace geom::operators
} // ~ namespace geom
#endif // ~ POINT_HPP
Class Segment:
#ifndef SEGMENT_HPP
#define SEGMENT_HPP
#include <iostream>
#include "point.hpp"
namespace geom_2d {
class Segment
{
public:
Segment(const geom::Point& a_, const geom::Point& b_) : a(a_), b(b_) {};
geom::Point a;
geom::Point b;
};
namespace operators {
std::ostream& operator<<(std::ostream& out, const Segment& p)
{
using namespace geom::operators;
out << "[" << p.a << ", " << p.b << "]";
return out;
}
} // ~ namespace geom_2d::operators
} // ~ namespace geom_2d
#endif // ~ SEGMENT_HPP
Main:
#include <iostream>
#include "segment.hpp"
#include "point.hpp"
using namespace geom_2d::operators;
int main()
{
geom::Point p1(3, 5);
geom::Point p2(1, 6);
geom_2d::Segment s(p1, p2);
std::cout << s << std::endl;
return 0;
}
This cannot compile and I get:
../segment.hpp:21: error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char, std::char_traits<char> >&)((std::ostream*)out)), ((const char*)"[")) << p->geom_2d::Segment::a’
If I remove namespace operators compiles correctly but as I told you, I want to avoid it.
I believe the problem has to do with calling using a namespace operators inside a another namespace operators.
Any ideas?
It is unclear why you want the operators to live in a different namespace than your types. In general the recommendation is that operators should live in the same namespace as the user defined types on which they operate. Doing so enables Argument Dependent Lookup, which in turn will help finding the correct operator when you use it (and will solve your compilation error).
If there is a real reason to have the operators in a different namespace, you can provide a tag type in that namespace and then use inheritance to force ADL to look into the nested namespace (the using-directive won't help with ADL):
namespace A {
namespace operators {
struct tag {};
}
struct B : operators::tag {};
namespace operators {
std::ostream& operator<<(std::ostream& out, const ::A::B& obj) { ... }
}
}
namespace C {
void foo() {
::A::B b;
std::cout << b;
}
}
Note that this is somehow of a hack, and some people will be surprised that the operators are not defined in the A namespace... it works because the set of associated namespaces for a type includes the namespace where the type is defined and also the namespaces of all of it's bases (in this case, ::A::operators is pulled due to the inheritance relationship between ::A::B and ::A::operators::tag)
NOTE: If you define the operators in the same namespace as the type, then you don't need the using-directive at all, as ADL will find them when needed.
The problem is that you've imported the namespace into your code via using, but the library headers don't do this. So they only find the operators in the global namespace, namespace std, or via argument-dependent lookup.
You can probably work around this by doing
using namespace geom_2d::operators;
before
#include <iostream>
but this seems to me like a poor solution.