Printing vectors from a class with private data without using friend function

I have code that adds two imaginary numbers and prints the results when the data are all public. This code is from an online tutorial I am following.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream> 
using namespace std; 
class complex {
public: 
    int real;
    int img;
    complex operator+(complex c)
    { 
        complex temp; 
        temp.real = real + c.real; 
        temp.img  = img + c.img; 
        return temp;
    }
};
int main()
{
    complex c1;
    complex c2; 
    complex c3;
    c1.real=3;
    c1.img=4;
    c2.real=6;
    c2.img=3;
    c3 = (c1 + c2);
    cout << "c1 = " << c1.real << " + " << c1.img << "i" << endl;
    cout << "c2 = " << c2.real << " + " << c2.img << "i" << endl;
    cout << "c3 = " << c3.real << " + " << c3.img << "i" << endl;
    return 0; 
}
// c1 = 3 + 4i
// c2 = 6 + 3i
// c3 = 9 + 7i 


I also have located code that does the same thing when the data are private by using a friend function. I found the friend function on a different online tutorial site.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream> 
using namespace std; 
class complex { 
private: 
    int real;
    int img;
public: 
    complex(int r=0, int i=0) 
    {
        real = r;
        img  = i;
    }
    complex operator+(complex c)
    { 
        complex temp; 
        temp.real = real + c.real; 
        temp.img  = img + c.img; 
        return temp;
    }
    friend ostream& operator<<(ostream& out, const complex& c);
};
ostream& operator<<(ostream& out, const complex& c) 
{
    out << c.real << " + " << c.img << "i"; 
    return out; 
}
int main()
{
    complex c1(3, 4);
    complex c2(6, 3); 
    complex c3;
    c3 = (c1 + c2);
    cout << "c1 = " << c1 << endl;
    cout << "c2 = " << c2 << endl;
    cout << "c3 = " << c3 << endl;
    return 0; 
}

// c1 = 3 + 4i
// c2 = 6 + 3i
// c3 = 9 + 7i 


Is it possible to use the cout statements from the first code example inside the second code example and remove the friend function and existing cout statements from that second code example? When I try I get errors saying the data are private.

1
2
3
    cout << "c1 = " << c1.real << " + " << c1.img << "i" << endl;
    cout << "c2 = " << c2.real << " + " << c2.img << "i" << endl;
    cout << "c3 = " << c3.real << " + " << c3.img << "i" << endl;


you can print out the private members you just can't do it from main. You have to write a method (function inside of the class) that prints out the data and call said method from main.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class complex {
private:
    int real;
    int img;
public:
    complex(int r = 0, int i = 0)
    {
        real = r;
        img = i;
    }

    void print() { cout << real; }

};

int main() {
    complex().print();

}
Last edited on
You can't use private members outside of the class without making the function(s) that use them friend functions. This is by definition. You can, however, define main() to be a friend function (but why? that defeats having private members!).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
using namespace std;

class complex {
	int real {};
	int img {};

public:
	complex(int r = 0, int i = 0) : real(r), img(i) {}
	complex(const complex& c) : real(c.real), img(c.img) {}

	complex operator+(complex c) {
		c.real += real;
		c.img += img;
		return c;
	}

	friend ostream& operator<<(ostream& out, const complex& c);
	friend int main();
};

ostream& operator<<(ostream& out, const complex& c)
{
	out << c.real << " + " << c.img << "i";
	return out;
}

int main()
{
	complex c1(3, 4);
	complex c2(6, 3);
	complex c3 {c1 + c2};

	cout << "c1 = " << c1 << endl;
	cout << "c2 = " << c2 << endl;
	cout << "c3 = " << c3 << endl;

	cout << "c1 = " << c1.real << " + " << c1.img << "i" << endl;
	cout << "c2 = " << c2.real << " + " << c2.img << "i" << endl;
	cout << "c3 = " << c3.real << " + " << c3.img << "i" << endl;
}



c1 = 3 + 4i
c2 = 6 + 3i
c3 = 9 + 7i
c1 = 3 + 4i
c2 = 6 + 3i
c3 = 9 + 7i


Also note the changes made to operator+()

Last edited on
Thank you, seeplus and markyrocks. That is very helpful.
There is no need to have std::ostream operator<< be a friend as long as the class has public retrieval methods for the real and imaginary components so operator<< can access them:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>

class Complex
{
   int real;
   int imag;

public:
   Complex(int r = 0, int i = 0)
      : real(r), imag(i)
   {}
   Complex(const Complex& c)
      : real(c.real), imag(c.imag)
   {}

public:
   Complex operator+(Complex c)
   {
      c.real += real;
      c.imag += imag;
      return c;
   }

public:
   int getReal() const { return real; }
   int getImag() const { return imag; }
};

std::ostream& operator<<(std::ostream&, const Complex&);

int main()
{
   Complex c1;
   Complex c2(2, 3);
   Complex c3(c1 + c2);

   std::cout << "c1: " << c1 << '\n';
   std::cout << "c2: " << c2 << '\n';
   std::cout << "c3: " << c3 << '\n';
}

std::ostream& operator<<(std::ostream& os, const Complex& cmp)
{
   os << cmp.getReal() << " + " << cmp.getImag() << "i";

   return os;
}

C++ already uses the complex keyword in the <complex> header, so capitalizing the custom class name as Complex is less likely to produce name collisions.
https://en.cppreference.com/w/cpp/numeric/complex

Having accessor methods for real and imag is how the <complex> library manages a complex number.

Printing vectors

The keyword vector has a different meaning in C++ than it has in math. A C++ vector is a container, similar to an array.
https://en.cppreference.com/w/cpp/container/vector

It is possible to have a std::vector that holds a custom class such as Complex. Overloading std:ostream::operator<< for the vector makes displaying the contents of a vector as simple as displaying a single Complex.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <vector>

class Complex
{
   int real;
   int imag;

public:
   Complex(int r = 1, int i = 0)
      : real(r), imag(i)
   {}
   Complex(const Complex& c)
      : real(c.real), imag(c.imag)
   {}

public:
   Complex operator+(Complex c)
   {
      c.real += real;
      c.imag += imag;
      return c;
   }

public:
   int getReal() const
   {
      return real;
   }
   int getImag() const
   {
      return imag;
   }
};

std::ostream& operator<<(std::ostream&, const Complex&);
std::ostream& operator<<(std::ostream&, const std::vector<Complex>&);

int main()
{
   Complex c1;
   Complex c2(2, 3);
   Complex c3(c1 + c2);

   std::cout << "c1: " << c1 << '\n';
   std::cout << "c2: " << c2 << '\n';
   std::cout << "c3: " << c3 << "\n\n";

   std::vector<Complex> vec;

   vec.push_back(Complex());
   vec.emplace_back(Complex(3, 5));
   vec.push_back(vec[0] + vec[1]);

   std::cout << vec;
}

std::ostream& operator<<(std::ostream& os, const Complex& cmp)
{
   os << cmp.getReal() << " + " << cmp.getImag() << "i";

   return os;
}

std::ostream& operator<<(std::ostream& os, const std::vector<Complex>& v)
{
   for (const auto& itr : v)
   {
      os << itr << '\n';
   }

   return os;
}

Topic archived. No new replies allowed.