友元函数与命名空间
发现问题
有以下的源代码文件:
1. Person.h
#ifndef Person_H
#define Person_H
#include<string>
namespace Test
{
using std::string;
using std::ostream;
class Person{
private:
string first_name_;
string last_name_;
public:
Person(string fn="unknow",string ln="unknow");
~Person();
//重载<<为友元函数
friend ostream& operator<<(ostream &os,const Person &p);
};
} // namespace Test
#endif
2. Person.cpp
#include"Person.h"
#include<iostream>
Test::Person::Person(string fn,string ln){
first_name_=fn;
last_name_=ln;
}
Test::Person::~Person(){
//do nothing
}
std::ostream & Test::operator<<(ostream &os,const Test::Person &p){
os<<"Name: "<<p.first_name_<<", "<<p.last_name_<<std::endl;
return os;
}
3. main.cpp
#include"Person.h"
#include<iostream>
int main(){
using namespace Test;
Person one("firstname","lastname");
std::cout<<one;
std::cin.get();
return 0;
}
对其进行编译的过程中出现了warning,其内容如下:
.\Person.cpp:11:16: warning: 'std::ostream& Test::operator<<(std::ostream&, const Test::Person&)' has not been declared within 'Test'
std::ostream & Test::operator<<(ostream &os,const Test::Person &p){
^~~~
In file included from .\Person.cpp:1:
.\Person.h:16:25: note: only here as a 'friend'
friend ostream& operator<<(ostream &os,const Person &p);
^~~~~~~~
问题分析
warning提示在Test中没有声明。因此,解决思路有两个,第一个是单独声明,另一个是将声明和定义同时进行。这里需要理解,friend友元声明只是描述了类和友元函数的关系,实际上并不是函数的声明。因此,需要在命名空间中单独声明。
解决方案
1.在命名空间中单独声明函数
friend友元声明只是告诉Person类,这个函数是友元函数,拥有相关的访问权限。但是友元函数并不属于Person类,因此需要在命名空间中单独声明,如下所示:
//在Person.h中
namespace Test
{
using std::string;
using std::ostream;
class Person{
private:
string first_name_;
string last_name_;
public:
Person(string fn="unknow",string ln="unknow");
~Person();
//重载<<为友元函数
friend ostream& operator<<(ostream &os,const Person &p);
};
//函数在命名空间中声明
ostream& operator<<(ostream &os,const Person &p);
} // namespace Test
2.在命名空间中同时声明并定义函数
在定义函数时不使用using或者域解析运算符,直接在命名空间中进行实现,及使用namespace进行包裹。此时,由于Person的定义和operator<<函数在同一个命名空间中,因此可以看作函数声明和定义是一起实现的,不会再出现未声明的警告。如下所示:
//在Person.cpp中
namespace Test{
Person::Person(string fn,string ln){
first_name_=fn;
last_name_=ln;
}
Person::~Person(){
//do nothing
}
std::ostream & operator<<(ostream &os,const Person &p){
os<<"Name: "<<p.first_name_<<", "<<p.last_name_<<std::endl;
return os;
}
}
以上方法采用其中一种即可。
Comments | NOTHING