I am trying to overload the class operator for istream (>>) and I am getting the error Ambiguous overload for operator>> for some reason. The operator for ostream works perfectly but istream does not.
Does someone know why?
#include <iostream>
#include <fstream>
using namespace std;
class Person
{
public:
Person(string name="Empty", int num=0)
:name(name), num(num){}
friend istream& operator>> (istream& is, Person& o)
{
is >> o.name>> o.num;
return is;
}
friend ostream& operator<< (ostream& os, Person& o)
{
return os << o.name<< " " << o.num<< endl;
}
private:
string name;
int num;
};
int main()
{
ifstream fajl("input.txt");
Person a();
fajl >> a ;
cout << a ;
}
input.txt:
Name1 15
Name2 16
I get the error in line: fajl >> a ;
This is not a variable declaration:
Person a();
is a function declaration. The correct code to declare a variable is:
Person a;
Related
Reading some documentation online I found that istream class was part of C++ long before the string class was added. So the istream design recognizes basic C++ types such as double and int, but it is ignorant of the string type. Therefore, there are istream class methods for processing double and int and other basic types, but there are no istream class methods for processing string objects.
My question is if there are no istream class methods for processing string objects, why this program works and how ?
#include <iostream>
int main(void)
{
std::string str;
std::cin >> str;
std::cout << str << std::endl;
return 0;
}
This is possible with the use operator overloading. As shown in the below example, you can create your own class and overload operator>> and operator<<.
#include <iostream>
class Number
{
//overload operator<< so that we can use std::cout<<
friend std::ostream& operator<<(std::ostream &os, const Number& num);
//overload operator>> so that we can use std::cin>>
friend std::istream &operator>>(std::istream &is, Number &obj);
int m_value = 0;
public:
Number(int value = 0);
};
Number::Number(int value): m_value(value)
{
}
std::ostream& operator<<(std::ostream &os, const Number& num)
{
os << num.m_value;
return os;
}
std::istream &operator>>(std::istream &is, Number &obj)
{
is >> obj.m_value;
if (is) // check that the inputs succeeded
{
;//do something
}
else
{
obj = Number(); // input failed: give the object the default state
}
return is;
}
int main()
{
Number a{ 10 };
std::cout << a << std::endl; //this will print 10
std::cin >> a; //this will take input from user
std::cout << a << std::endl; //this will print whatever number (m_value) the user entered above
return 0;
}
By overloading operator>> and operator<<, this allows us to write std::cin >> a and std::cout << a in the above program.
Similar to the Number class shown above, the std::string class also makes use of operator overloading. In particular, std::string overloads operator>> and operator<<, allowing us to write std::cin >> str and std::cout << str, as you did in your example.
Because std::string overload the >> and << operator to return the type std::istream and std::ostream
How they overload it, you can look in this link that Mat gives.
You can create your own class and overload operators, too. Here is an example:
class MyClass
{
int numberOne;
double numberTwo;
public:
friend std::ostream& operator<<(std::ostream &out, const MyClass& myClass);
friend std::istream& operator>> (std::istream& in, MyClass& myClass);
};
// Since operator<< is a friend of the MyClass class, we can access MyClass's members directly.
std::ostream& operator<<(std::ostream &out, const MyClass& myClass)
{
out << myClass.numberOne << ' ' << myClass.numberTwo;
return os;
}
// Since operator>> is a friend of the MyClass class, we can access MyClass's members directly.
std::istream& operator>> (std::istream& in, MyClass& myClass)
{
in >> myClass.numberOne;
in >> myClass.numberTwo;
return in;
}
int main()
{
MyClass myClass;
std::cin >> myClass;
std::cout << myClass;
}
Because of operator overloading.
In your case, including <iostream> will include <string>, a specialization of std::basic_string. And std::basic_string has the non-member functions operator<< and operator>> defined.
Similarly, you can also overload operator<< and operator>> for your own custom types.
I'm having some problems with my code. I declared in the .h two friend functions which are:
#ifndef CLASS2_H
#define CLASS2_H
#include "class1.h"
#include <string>
#include <iostream>
using namespace std;
class Class2{
private:
VD<Class1> data; //Vector of objects of Class1
VD<int> number; //Vector of int
public:
Constructor();
friend istream & operator >> (istream & i, const Class1 & other);
friend ostream & operator << (ostream &o, const Class1 & other);
};
#endif
And the .cpp is:
istream & operator >> (istream & i,Class2 & other){
string n;
Class1 ing;
getline(i,n);
while(!i.eof()){
i >> ing;
otro.data.Insert(ing,otro.data.size()-1);
}
return i;
}
ostream & operator << (ostream &o, const Ingredientes & otro){
for(int i = 0; i < otro.datos.size(); i++){
o << other.data[i];
}
return o;
}
So, the error that I'm getting is:
error: 'VD Class2::data' is private within this context. I declared the functions of operator >> y << friend but I doesn't make any sense that compiler says to me that I can't access to the private data. Any help please?
You seem to be very new at C++, and you seem to be doing quite complex things, while you're not understanding the basics yet. Please find a tutorial or so.
A few things:
using namespace std; is -especially in a header- never a good idea. It's like you're going on holiday, but bring along everything in your house. Refer to standard namespace functions using std::.
an istream& operator>>() cannot put anything in an object that is declared const.
using vec.insert(obj, vec.size()-1) is reinventing one of the most essential funcitons of std::vector: push_back()...
while (!i.eof()) is not good, because eof is not set until after the read past the end.
there's no string& operator>>(string& str, Class1& obj) function defined. We have std::stringstream for that.
To show how you could realize some of this, I'm going to write some example code. Please don't just copy it, but try to understand it.
test.txt
1 2 3 4
5 6 7 8
main.cpp
#include <vector>
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
template <typename T>
using VD = std::vector<T>;
class Class1 {
private:
int d;
public:
friend std::istream& operator>> (std::istream& i, Class1& obj) {
i >> obj.d;
return i;
}
friend std::ostream& operator<< (std::ostream& o, const Class1& obj) {
o << obj.d;
return o;
}
};
class Class2 {
private:
VD<Class1> data{}; //Vector of objects of Class1
public:
void Clear() { data.clear(); }
friend std::istream& operator>> (std::istream& i, Class2& obj) {
std::string line;
std::getline(i, line);
std::istringstream iss(line);
Class1 ing;
while (iss >> ing) {
obj.data.push_back(ing);
}
return i;
}
friend std::ostream& operator<< (std::ostream& o, const Class2& obj) {
for (auto const& cl1 : obj.data) {
o << cl1 << " ";
}
return o;
}
};
int main() {
Class2 cl2;
std::ifstream ifs;
ifs.open("test.txt");
if (ifs.is_open()) {
ifs >> cl2;
}
std::cout << "first line: " << cl2 << '\n';
cl2.Clear();
if (ifs.is_open()) {
ifs >> cl2;
}
std::cout << "second line: " << cl2 << '\n';
ifs.close();
}
I have another class object in my class. Ex:
ParkingMeter.h
class ParkingMeter
{
private:
ParkedCar pCar;
int minutesPurchased = 0;
public:
friend std::istream& operator >> (std::istream, ParkingMeter&);
};
ParkedCar.h
class ParkedCar
{
private:
std::string maker;
std::string model;
std::string color;
int licenseNumber = 0;
int minutesParked = 0;
public:
friend std::istream& operator >> (std::istream&, ParkedCar&);
friend std::ostream& operator << (std::ostream&, ParkedCar&);
};
So, when I enter the data for ParkingMeter object with it's respective operator overloaded, I want to call the overloaded function for the ParkedCar object aswell.
This is what I've got. The operator overloaded function for the ParkingMeter:
std::istream& operator>>(std::istream is, ParkingMeter& obj)
{
cout << "How many minutes to buy? ";
is >> obj.minutesPurchased;
cout << "Enter the information about your car:\n";
is >> obj.pCar;
return is;
}
But in my main file, the following code don't word:
ParkingMeter temp;
std::cin >> temp;
Thank you.
Solution
Thanks to #L. F. for pointing my silly mistake. :D
I've forgotten to use the & after std::istream in the arguments for the function:
friend std::istream& operator >> (std::istream, ParkingMeter&);
Now its works fine:
friend std::istream& operator >> (std::istream&, ParkingMeter&);
I try to overload ostream operator in a class Student as follows:
//Student.h
class Student
{
public:
Student(){}
~Student(){}
friend std::ostream& operator<< (std::ostream&,const Student&);
friend std::istream& operator>> (std::istream&,const Student&);
private:
char* snum;
};
//Student.cpp
#include "Student.h"
std::ostream& operator<< (std::ostream& output,const Student& c)
{
output<<c.snum<<", "<<c.name<<", "<<c.email<<endl;
return output;
}
std::istream& operator>> (std::istream& input,const Student& cN)
{
cout<<"Input number: ";
input>>cN.snum;
return input;
}
//main.cpp
#include "Student.h"
int main()
{
Student st;
std::cin >> st;
std::cout << st << std::endl;
return 0;
}
But when i input the snum,i get error message "Segmentation Fault".
I change char* snum; to char snum;,it return compiler error The operation "std::istream>> const char" is illegal.
Thank you for help.
You need that snum will point on allocate memory and then you can input it with data, for exemple:
char* p_var = new char[20]; // 20 bytes allocation
// ... using p_var
delete[] p_var; // Releasep_var memory
In your case, you should do the allocation in the Ctor and the release in the Dtor.
you can read this for more info:
http://www.cplusplus.com/doc/tutorial/basic_io/
tell me if your problem got solved by using below changes...
class Student
{
private:
char snum;
char name;
char email;
public:
Student(){};
~Student(){};
friend std::ostream& operator<< (std::ostream&,Student&);
friend std::istream& operator>> (std::istream&,Student&);
};
std::ostream& operator<< (std::ostream& output,Student& c)
{
output<<c.snum<<", "<<c.name<<", "<<c.email<<endl;
return output;
}
std::istream& operator>> (std::istream& input, Student& cN)
{
cout<<"Input number: ";
input>>cN.snum;
input>>cN.name;
input>>cN.email;
return input;
}
int main()
{
Student st;
std::cin >> st;
std::cout << st << std::endl;
return 0;
}
use string or char array or assign char *x some memory before using for cin...
Can anyone help me. Below is the code which I'm trying to execute. There is no compile time error but the program crashes when the control goes to string copy statement. I'm trying to fix it for almost one hour, but still not succeeded.
#include <iostream>
using namespace std;
class test
{
private:
char* name;
friend istream& operator >>(istream&, test&);
};
istream& operator >> (istream& is, test& t)
{
char c[20];
cout << "enter something";
is >> c;
strcpy(t.name, c);
return is;
}
int main()
{
test obj;
cin >> obj;
}
The name pointer is uninitialized by the time you are invoking strcpy, which gives your program undefined behavior.
To avoid this kind of problem, use std::string rather than C strings. More concretely, redefine your class this way:
#include <string> // Needed for std::string
class test
{
private:
std::string name;
friend istream& operator >>(istream&, test&);
};
To make your program compile, you could then adapt your overload of operator >> this way:
istream& operator >> (istream& is, test& t)
{
cout << "enter something";
is >> t.name;
return is;
}
Notice, however, that you should not prompt the user for information inside your extraction operator (i.e. inside the overload of operator >>). The insertion operator is only supposed to extract an object of type test from an input stream.
Thus, to provide a complete example:
#include <iostream>
#include <string>
class test
{
private:
std::string name;
friend std::istream& operator >>(std::istream&, test&);
};
std::istream& operator >> (std::istream& is, test& t)
{
is >> t.name;
return is;
}
int main()
{
test obj;
std::cout << "enter something: ";
std::cin >> obj;
}
Also avoid using directives such as:
using namespace std;
Especially if at namespace scope and especially if in a header (not your case, but still) - they tend to cause name clashes with entities that live in the std namespace.
EDIT:
Since it seems you are not allowed to use std::string, only the first sentence of the original answer remains valid - and the part about where you should be asking input from the user, perhaps.
So this is what you can write for assigning t.name a copy of the string input by the user:
t.name = strdup(c);
You will need to include the <cstring> standard header for strdup():
#include <cstring>
I would also suggest to initialize the name pointer to null in the constructor of the test class - it doesn't get initialized by the implicitly-generated default constructor:
class test
{
test() : name(nullptr) { } // Use NULL instead of nullptr in C++03
private:
char* name;
friend istream& operator >> (istream&, test&);
};
So in a complete program:
#include <iostream>
#include <cstring>
class test
{
public:
test() : name(nullptr) { }
private:
char* name;
friend std::istream& operator >>(std::istream&, test&);
};
std::istream& operator >> (std::istream& is, test& t)
{
char c[20];
is >> c;
t.name = strdup(c);
return is;
}
int main()
{
test obj;
std::cout << "enter something: ";
std::cin >> obj;
}