Namespaces, Classes, and Operator Overload

Hello all,

I'm doing a refresher for C++ and have gotten to operator overloading. I'm trying to perform an operator overload with the insertion (<<) operator, but I have encountered a problem.

Here's my class [In a header file "Shinigami.h"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<string> 
namespace K{
class Quincy; 
class Shinigami{
	friend std::ostream& operator<<(std::ostream&, const Shinigami&); 
public:
	Shinigami() {} 
	Shinigami(const std::string&, const std::string&, const int&);
	void shikai(); 
	void display(); 
private:
	std::string name;
	std::string zanpakuto; 
	int power; 
	K::Quincy* enemy; 
};
}


And the source file that defines its functions [Shinigami.cpp]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "Shinigami.h"
#include "Quincy.h" 
#include<iostream> 
using namespace K; 
Shinigami::Shinigami(const std::string& name, const std::string& zanpakuto, const int& power) : name(name), zanpakuto(zanpakuto), power(power) {} 

void Shinigami::display(){
	std::cout << name << std::endl
			  << "===============" << std::endl
			  << "Class: Shinigami" << std::endl
			  << "Zanpakuto: " << zanpakuto << std::endl
			  << "Power: " << power << std::endl; 
}
void Shinigami::shikai(){
	std::cout << name << ": I call upon thee " << zanpakuto << "!" << std::endl; 
}

std::ostream& operator<<(std::ostream& os, const Shinigami& rhs){
	return os;
}



---> This is the problem
1
2
3
4
5
 std::ostream& operator<<(std::ostream& os, const Shinigami& lhs){
        os << lhs.name << ":" << lhs.power << std::endl; 
	return os;
}


If the operator function is a friend of the 'Shinigami' class, why doesn't it recognize any of it's private members? I need it to be in this file because I'm doing a bit of association with the 'Quincy' class.

I thought it was the namespace, but I included that.

Any help is appreciated

~ xAnimeAngiex ~
http://stackoverflow.com/questions/2207219/how-do-i-define-friends-in-global-namespace-within-another-c-namespace
In you case you need to put
1
2
namespace K{ class Shinigami; }
std::ostream& operator<<(std::ostream&, const K::Shinigami&);
on top of your header (This is forward declaration) and change declaration inside class to: friend std::ostream& (::operator<<)(std::ostream&, const Shinigami&);
That didn't work, it's private members are still inaccessible.
Btw, I don't have to use a forward declaration since I'm including the class with the header 'Shinigami.h'.
Did you read the article I provided? Did you tried what I proposed exactly? If so, show, how your header looks after that.
Because it works with changes I propose for me.
Last edited on
Btw, I don't have to use a forward declaration since I'm including the class with the header 'Shinigami.h'.


Uh, no, you do need to use forward declaration as @NiiNiPaa said. The forward declaration has to be within the header file, forward declaring something fully declared later in the same file.

You need to
- forward delcare K::Shinigami
- then foward declare operator<<(std::ostream&, const K::Shinigami&)
- then declare K::Shinigami, with it's friend, which was just forward declared.
Less work and just as productive would be to leave operator>> in the K namespace and just change the definition slightly:

1
2
3
4
std::ostream& K::operator<<(std::ostream& os, const K::Shinigami& rhs){
    os << rhs.name << ":" << rhs.power << std::endl; 
	return os;
}



Note the K:: prefix to operator<<.
Good name for class :D
Thanks MiiNiPaa; i was wrong, the code compiled and worked as expected. But, would you mind explaining how this works? Like why do do I have to make a forward declaration for the namespace and (prototype?) for the operator overload. Also, what's the deal with this (::operator<<) ?

Thanks :D

~ Anime Angie x ~
:: is a scope resolution operator. ::operator<< tells, that operator<< is in global namespace. For some reason compiler doesn't accept this as declaration and gives an error operator<< isn't declared. So we need forward declaration of operator in global namespace. If we do so, compiler will tell, that class K::Shinigami wasn't declared, so we need to forward declare class Shinigami inside K namespace.

cire's method will work too. I had doubts if operator will work without using namespace K; or K:: specification for operator, but other sources told me that everything will be fine.
Gotcha, thanks.
Topic archived. No new replies allowed.