I'm writing a program that requires me to overload the << operator whilst accessing private members of the class. It goes like this:
A.h
#pragma once
#include <ostream>
#include "B.h"
using namespace std;
class A {
public:
A(B* b) {
this->b = b;
this->x = 0;
}
friend ostream& operator<<(ostream& os, A& a)
{
os << "this is a " << a.x;
return os;
}
private:
int x;
B* b;
};
B.h
#pragma once
#include <ostream>
using namespace std;
class B {
public:
B(int x) {
this->x = x;
}
friend ostream& operator<<(ostream& os, B& b)
{
os << "this is B " << b.x;
return os;
}
private:
int x;
};
main.cpp
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
int main()
{
B* b = new B(1);
A* a = new A(b);
cout << a << endl;
cout << b << endl;
}
However, this doesn't print a and b, just the memory address of the two objects. I think it has something to do with the order of operations, but I'm not sure on that.
Also, I can't use ostream& operator<<() as an independent function since that would prevent me from accessing the private member of the class.
I could potentially implement a void print() inside the class and use that to print the private members, but I don't think that's what my professor has in mind (considering there's already a void print() implemented for something else).
In main(), a and b are pointers. This code:
cout << a
cout << b
Is effectively calling this:
cout.operator<<(a)
cout.operator<<(b)
Because std::ostream has a member operator<<(void*) for printing a pointer, and all pointers are implicitly convertible to void*. This is why you are seeing memory addresses in the output. Your custom operators are not being called at all, as they require you to pass actual object instances to operator<<, which you are not doing.
You need to dereference your pointers in main(), eg:
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
int main()
{
B* b = new B(1);
A* a = new A(b);
cout << *a << endl;
cout << *b << endl;
delete a;
delete b;
}
In this code:
cout << *a
cout << *b
Since std::ostream does not have member operator<<s for A or B, this will effectively call this instead:
operator<<(cout, *a)
operator<<(cout, *b)
Which will call your custom operators.
Otherwise, simply get rid of the pointers altogether:
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
int main()
{
B b(1);
A a(&b);
cout << a << endl;
cout << b << endl;
}
Which will also effectively call this:
operator<<(cout, a)
operator<<(cout, b)
Thus calling your custom operators.
On a side note, your custom operators should be accepting references to const A+B objects, eg:
friend ostream& operator<<(ostream& os, const A& a)
friend ostream& operator<<(ostream& os, const B& b)
Related
So here's the problem. I have a class B where I have overloaded the << operator and a class A where the << operator is also overloaded. However, the << overload in class B doesn't seem to be working in the << overload in class A. It simply returns the address of b as if the << overload in class B doesn't exist.
Any help would be very appreciated
#pragma once
#include <ostream>
using namespace std;
class B {
public:
B(int x) {
this->x = x;
}
friend ostream& operator<<(ostream& os, B& b)
{
os << "this is B " << b.x;
return os;
}
private:
int x;
};
#pragma once
#include <ostream>
#include "B.h"
using namespace std;
class A {
public:
A(B* b) {
this->b = b;
this->x = 0;
}
friend ostream& operator<<(ostream& os, A& a)
{
os << a.b << endl; //this doesnt work <============
os << "this is a " << a.x;
return os;
}
private:
int x;
B* b;
};
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
int main()
{
B* b = new B(1);
A* a = new A(b);
cout << *a << "inside a "<< endl;
cout << *b << "inside b " <<endl;
}
os << a.b // ...
a.b is not a B, for which you defined an overload, look closer at your code:
class A {
private:
B* b;
};
That's a B *, and not a B, and no overload exists for that.
If you want to call the overload here, use os << (*a.b) // ...;
In the class base, we need to write a function such that printing an object will print arguments of an object using oops concept.
#include <iostream>
using namespace std;
class base{
int num;
string s;
public:
base(int elem,string p){
cout<<elem<<" "<<p<<endl;
}
// todo:
};
int main() {
base obj(12,"shivam");
// cout<<obj<<endl;
}
Your current idea is not far from working, except you print the constructor arguments to std::cout as soon as an instance of base is created - not when the programmer using the class expresses such a wish. What you need to do is to save the arguments given when constructing a base. You'll then be able to print them on demand.
Example:
#include <iostream>
#include <string>
class base {
public:
base(int n, const std::string& str) : // save the arguments given using
num(n), s(str) // <- the member initializer list
{
// empty constructor body
}
// declare a friend function with special privileges to read private
// member variables and call private functions:
friend std::ostream& operator<<(std::ostream&, const base&);
private:
int num;
std::string s;
};
// define the free (friend) function with access to private base members:
std::ostream& operator<<(std::ostream& os, const base& b) {
// here you format the output as you'd like:
return os << '{' << b.num << ',' << b.s << '}';
}
int main() {
base obj(12,"shivam");
std::cout << obj << '\n';
}
Output:
{12,shivam}
Try this:
int IntS(int y)
{
return y;
}
class base{
public:
base(int enume, std::string str)
{
std::cout << IntS(enume) << '\n';
std::cout << str << '\n;
}
};
int main()
{
base mybase(IntS(5), "five");
return 0;
}
See also, std::map:
How can I print out C++ map values?
As far as I know in C++ we cannot use the same identifier for another declaration:
int x;
char x; // compile-time error: redefinition.
But here is an example where I was messing with classes:
#include "stdafx.h"
#include <iostream>
#include <vector>
class A {
public:
A(int);
void print()const;
friend std::ostream& operator << (std::ostream& out, A& rhs);
private:
int value1;
};
std::ostream& operator << (std::ostream& out, A& rhs) {
out << "rhs.value1 = " << rhs.value1 << std::endl;
return out;
}
A::A(int x) : value1(x) { std::cout << "ctor A(x)" << std::endl; }
void A::print()const {
std::cout << "value1: " << value1 << std::endl;
}
int A(int x) {
std::cout << "inside A(int x)" << std::endl;
return x;
}
int main(){
class A a { 0 };
a = A(7);
a.print();
std::cout << A(7) << std::endl;
std::cout << A(5) << std::endl; // here if I comment out the function a it is ok as long as I overloaded the insertion operator
// and if I add the function A it hides the insertion operator!
std::cout << std::endl;
std::cin.get();
return 0;
}
So as you can see above I must add the keyword class whenever I declare an object of class Aotherwise I get a compile-time error. Why?
Is the expression a = A(7); a function call and the return value is passed to the constructor of class A that takes an integer. Or simply no function call but only ctor call?
From my point of view, you have a class A and a function A, so you have to point out A is a class or a function that's why you have to add "class" when you declare an object of A.
According to the following code, two classes, A and B, are defined, they are exactly same, but A can be a function or a class, so when you declare a object A, you have to add a "class" before A, while declare a object of B is no need to add a "class"
For the second question, first function A is called, and its return value is used to construct object a. You can see first x=7 is in the function A, and ctor x=8 because the function return x+1.
The output:
ctor A(x) x=0
inside A(int x) x=7
ctor A(x) x=8
ctor B(x)
The test code:
#include <iostream>
#include <vector>
class A {
public:
A(int);
private:
int value1;
};
class B {
public:
B(int);
private:
int value1;
};
B::B(int x) : value1(x) { std::cout << "ctor B(x)" << std::endl; }
A::A(int x) : value1(x) { std::cout << "ctor A(x) x=" << x <<std::endl; }
int A(int x) {
std::cout << "inside A(int x) x=" << x << std::endl;
x=x+1;
return x;
}
int main(){
class A a(0);
a = A(7);
B b(0);
return 0;
}
I'm trying to return a tuple, one of the elements of which is a std::unique_ptr. I want to transfer the ownership of the unique_ptr to the caller. How do I do this?
#include <tuple>
#include <memory>
#include <iostream>
using namespace std;
class B
{
public:
B(int i) : i_(i) {}
int getI() const { return i_; }
private:
int i_;
};
tuple<unique_ptr<B>, int>
getThem()
{
unique_ptr<B> ptr(new B(10));
return make_tuple(ptr, 50);
}
int
main(int argc, char *argv[])
{
unique_ptr<B> b;
int got = 0;
tie(b, got) = getThem();
cout << "b: " << b->getI() << endl;
cout << "got: " << got << endl;
return 0;
}
This fails to compile because the copy constructor of unique_ptr is deleted, for obvious reasons. But how to I indicate I want to move the unique_ptr into the tie?
Essentially you just need to explicitly move the non-copyable types into the tuple, thus using std::move. std::tuple has the appropriate constructors to copy and move the types internally (the move being appropriate here).
As follows;
#include <tuple>
#include <memory>
#include <iostream>
using namespace std;
class B
{
public:
B(int i) : i_(i) {}
int getI() const { return i_; }
private:
int i_;
};
tuple<unique_ptr<B>, int>
getThem()
{
unique_ptr<B> ptr(new B(10));
return make_tuple(std::move(ptr), 50); // move the unique_ptr into the tuple
}
int
main(int argc, char *argv[])
{
unique_ptr<B> b;
int got = 0;
tie(b, got) = getThem();
cout << "b: " << b->getI() << endl;
cout << "got: " << got << endl;
return 0;
}
Use std::move to invoke the move operator instead.
return make_tuple(std::move(ptr), 50);
Hello I currently face a problem were I want to output data from 2 separate classes, one is a base class and one is a derived class, I want to overload the << operator to output all the data at once but seem to have trouble doing so, I have something like this:
#include <iostream>
using namespace std;
class A
{
char* A;
char* B;
public:
A() {A = ' '; B = ' ';}
A(char* pLast, char* pFirst)
{
A = new char [strlen(pLast) + 1];
B = new char [strlen(pFirst) + 1];
strcpy(A,pLast);
strcpy(B,pFirst);
};
}
class C:public A
{
int X;
char Y;
int Z;
public:
C(char* A, char* B, int X, char Y, int Z)
:A(A,B)
{
//do stuff here
}
friend std::ostream& operator<<(std::ostream& out, const C& outPut)
{
out << outPut.A << "," << outPut.B << "," <<outPut.X<< "," << outPut.Y << "," << outPut.Z << endl;
return out;
}
};
When I try to run this it tells me A and B are out of range which makes sense since those members are private in class A, I don't know how to get around this. I tried creating getter methods to access A and B but the data comes out as blank. I even tried added an object of class A as a member of class B to try to allow access to the members in class B still the data comes out blank. How do I get around this problem?
There are several ways of dealing with this. One way obviously is to make the members of A protected rather than private. A derived class B can then access them.
Another way indeed are getter functions. The fact they didn't work for you is related to problems in your constructors and other problems in your code. But public getters also have the disadvantage of enabling anyone (not just derived classes) to get access to the values of your data members.
Here is a third approach, which I believe makes sense in your case: Define a separate operator<< in A, and make use of that operator when you define the one for B:
#include <cstring>
#include <iostream>
using namespace std;
class A
{
char* _a;
char* _b;
public:
A()
: _a(),_b()
{ }
A(const char *pLast, const char *pFirst)
: _a(new char [std::strlen(pLast)]),
_b(new char [std::strlen(pFirst)])
{
strcpy(_a,pLast);
strcpy(_b,pFirst);
}
friend std::ostream& operator<<(std::ostream& out, const A& obj)
{
out << obj._a << "," << obj._b;
return out;
}
};
class B : public A
{
int _x;
char _y;
int _z;
public:
B(const char *pLast, const char *pFirst, int x, char y, int z)
: A(pLast,pFirst),
_x(x),_y(y),_z(z)
{ }
friend std::ostream& operator<<(std::ostream& out, const B& obj)
{
out << static_cast<const A&>(obj) << ','
<< obj._x << ','
<< obj._y << ','
<< obj._z;
return out;
}
};
int main()
{
B b("hello","world",1,'a',3);
std::cout << b << std::endl;
return 0;
}
I've also corrected the other problems I found, so the above actually works.