关于命名空间和友元函数的问题

痕枫冷 2012-08-20 02:17:31
加了个自定义命名空间,是不是友元函数无法访问类的私有成员了?
请大神们看看下面的代码,看看怎么改?
Person类

namespace liuyx{
#ifndef PERSON_H
#define PERSON_H
class Person
{
friend Person operator+(const Person&,const Person&);
friend std::ostream& operator<<(std::ostream&,const Person&);
friend std::istream& operator>>(std::istream&,Person& p);
public:
Person(const std::string& nm="",int a=0,int s=0):name(nm),age(a),salary(s){};
Person(const Person& p){
name = p.name;
age = p.age;
salary = p.salary;
}
Person& operator=(const Person& p){
name = p.name;
age = p.age;
salary = p.salary;
return *this;
}
Person& operator+=(const Person& p){
if(!this->same_name(p))
throw std::runtime_error("The two param must be the same type Person");
salary += p.salary;
return *this;
}

const bool same_name(const Person& p)const{
return name == p.name;
}
private:
std::string name;
int age;
int salary;
};
#include "Person.cpp"
#endif
}

Person类的实现文件Person.cpp

#include "Person.h"
namespace liuyx{
Person operator+(const Person& p1,const Person& p2){
Person p = p1;
p += p2;
return p;
}
std::ostream& operator<<(std::ostream& os, const Person& p){
os << "name: " << "\t" << p.name
<< "\nage: " << "\t" << p.age
<< "\nsalary: " << "\t" << p.salary;
return os;
}
std::istream& operator>>(std::istream& is,Person &p){
std::cout << "Enter a person's name first,then age,and then salary:"<< std::endl;
is >> p.name >> p.age >> p.salary;
if(!is)
p = Person();
return is;
}
}



测试类:
#include <iostream>
#include <string>
#include "Person.h"
using namespace std;
using liuyx::Person;
using liuyx::operator +;
using liuyx::operator <<;
using liuyx::operator >>;
int main(){
Person p1,p2;
std::cin >> p1 >> p2;
try{
p1 += p2;
}catch(...){
throw;
}
std::cout << p1 << endl;
return 0;
}


最后提示友元函数无法访问类的私有成员

出错信息如下:

1>------ 已启动生成: 项目: t, 配置: Debug Win32 ------
1>正在编译...
1>main.cpp
1>c:\documents and settings\user\桌面\c++\t\t\Person.cpp(12) : error C2248: “liuyx::Person::name”: 无法访问 private 成员(在“liuyx::Person”类中声明)
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(33) : 参见“liuyx::Person::name”的声明
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(5) : 参见“liuyx::Person”的声明
1>c:\documents and settings\user\桌面\c++\t\t\Person.cpp(13) : error C2248: “liuyx::Person::age”: 无法访问 private 成员(在“liuyx::Person”类中声明)
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(34) : 参见“liuyx::Person::age”的声明
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(5) : 参见“liuyx::Person”的声明
1>c:\documents and settings\user\桌面\c++\t\t\Person.cpp(13) : error C2248: “liuyx::Person::salary”: 无法访问 private 成员(在“liuyx::Person”类中声明)
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(35) : 参见“liuyx::Person::salary”的声明
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(5) : 参见“liuyx::Person”的声明
1>c:\documents and settings\user\桌面\c++\t\t\Person.cpp(18) : error C2248: “liuyx::Person::name”: 无法访问 private 成员(在“liuyx::Person”类中声明)
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(33) : 参见“liuyx::Person::name”的声明
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(5) : 参见“liuyx::Person”的声明
1>c:\documents and settings\user\桌面\c++\t\t\Person.cpp(18) : error C2248: “liuyx::Person::age”: 无法访问 private 成员(在“liuyx::Person”类中声明)
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(34) : 参见“liuyx::Person::age”的声明
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(5) : 参见“liuyx::Person”的声明
1>c:\documents and settings\user\桌面\c++\t\t\Person.cpp(18) : error C2248: “liuyx::Person::salary”: 无法访问 private 成员(在“liuyx::Person”类中声明)
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(35) : 参见“liuyx::Person::salary”的声明
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(5) : 参见“liuyx::Person”的声明
1>生成日志保存在“file://c:\Documents and Settings\user\桌面\C++\t\t\Debug\BuildLog.htm”
1>t - 6 个错误,0 个警告
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========



麻烦帮忙看看是什么问题,谢谢~!
...全文
294 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
冰旋栀子 2012-08-20
  • 打赏
  • 举报
回复
学学,函数定义和声明的时候注意命名空间,一般函数声明的时候需要用到命名空间,而函数定义的时候要用using namespace liuyx,拙见,仅供参考!
痕枫冷 2012-08-20
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

为什么在头文件中包括Person.cpp? 删除该行试试.

#include "Person.cpp"
#endif

另你包含stdexecpt头文件.
[/Quote]
包含“Person.cpp”,让头文件去找寻Person的实现类。删除该行后,编译连接的时候也报错了,报错信息如下:

1>------ 已启动生成: 项目: t, 配置: Debug Win32 ------
1>正在编译...
1>Person.cpp
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(7) : error C2653: “std”: 不是类或命名空间名称
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(7) : error C2143: 语法错误 : 缺少“;”(在“&”的前面)
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(7) : error C2433: “liuyx::ostream”: 不允许在数据声明中使用“friend”
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(7) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(7) : error C2653: “std”: 不是类或命名空间名称
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(7) : error C2061: 语法错误 : 标识符“ostream”
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(7) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(7) : error C2805: 二进制“operator <<”的参数太少
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(8) : error C2653: “std”: 不是类或命名空间名称
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(8) : error C2143: 语法错误 : 缺少“;”(在“&”的前面)
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(8) : error C2433: “liuyx::istream”: 不允许在数据声明中使用“friend”
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(8) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(8) : error C2653: “std”: 不是类或命名空间名称
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(8) : error C2061: 语法错误 : 标识符“istream”
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(8) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(8) : error C2805: 二进制“operator >>”的参数太少
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(10) : error C2653: “std”: 不是类或命名空间名称
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(10) : error C2653: “std”: 不是类或命名空间名称
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(10) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(10) : error C2143: 语法错误 : 缺少“,”(在“&”的前面)
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(33) : error C2653: “std”: 不是类或命名空间名称
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(33) : error C2146: 语法错误 : 缺少“;”(在标识符“name”的前面)
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(33) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(33) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(10) : error C2065: “nm”: 未声明的标识符
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(10) : error C2065: “a”: 未声明的标识符
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(10) : error C2065: “s”: 未声明的标识符
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(10) : error C2614: “liuyx::Person”: 非法的成员初始化:“name”不是基或成员
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(12) : error C2065: “name”: 未声明的标识符
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(12) : error C2039: “name”: 不是“liuyx::Person”的成员
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(5) : 参见“liuyx::Person”的声明
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(17) : error C2039: “name”: 不是“liuyx::Person”的成员
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(5) : 参见“liuyx::Person”的声明
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(24) : error C2653: “std”: 不是类或命名空间名称
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(24) : error C3861: “runtime_error”: 找不到标识符
1>c:\documents and settings\user\桌面\c++\t\t\Person.h(30) : error C2039: “name”: 不是“liuyx::Person”的成员
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(5) : 参见“liuyx::Person”的声明
1>.\Person.cpp(9) : error C2653: “std”: 不是类或命名空间名称
1>.\Person.cpp(9) : error C2143: 语法错误 : 缺少“;”(在“&”的前面)
1>.\Person.cpp(9) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>.\Person.cpp(9) : error C2086: “int liuyx::ostream”: 重定义
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(7) : 参见“liuyx::ostream”的声明
1>.\Person.cpp(9) : error C2653: “std”: 不是类或命名空间名称
1>.\Person.cpp(9) : error C2065: “os”: 未声明的标识符
1>.\Person.cpp(9) : error C2059: 语法错误 : “const”
1>.\Person.cpp(9) : error C2143: 语法错误 : 缺少“;”(在“{”的前面)
1>.\Person.cpp(9) : error C2447: “{”: 缺少函数标题(是否是老式的形式表?)
1>.\Person.cpp(15) : error C2653: “std”: 不是类或命名空间名称
1>.\Person.cpp(15) : error C2143: 语法错误 : 缺少“;”(在“&”的前面)
1>.\Person.cpp(15) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>.\Person.cpp(15) : error C2086: “int liuyx::istream”: 重定义
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(8) : 参见“liuyx::istream”的声明
1>.\Person.cpp(15) : error C2653: “std”: 不是类或命名空间名称
1>.\Person.cpp(15) : error C2065: “is”: 未声明的标识符
1>.\Person.cpp(15) : error C2065: “p”: 未声明的标识符
1>.\Person.cpp(15) : error C2275: “liuyx::Person”: 将此类型用作表达式非法
1> c:\documents and settings\user\桌面\c++\t\t\Person.h(5) : 参见“liuyx::Person”的声明
1>.\Person.cpp(15) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>.\Person.cpp(15) : fatal error C1903: 无法从以前的错误中恢复;正在停止编译
1>生成日志保存在“file://c:\Documents and Settings\user\桌面\C++\t\t\Debug\BuildLog.htm”
1>t - 53 个错误,0 个警告
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========


疯了~!
seanxq 2012-08-20
  • 打赏
  • 举报
回复
为什么在头文件中包括Person.cpp? 删除该行试试.

#include "Person.cpp"
#endif

另你包含stdexecpt头文件.
这是DS小龙哥编写整理的C++入门指南PDF文档,适合C++初学者,C语言转C++工程师当做入门工具书学习。PDF里有完整示例、知识讲解,平时开发都可以复制粘贴,非常便捷。 目前一共写了7章,后续会持续更新资源包,更新后重新下载即可。 这是目前书籍的目录: C++入门指南 1 一、 C++语言基本介绍与开发环境搭建 1 1.1 C++简介 1 1.2 面向对象编程 1 1.3 Windows系统下搭建C++学习环境 2 二、C++基础入门 16 2.1 C++类和对象 17 2.2 C++命名空间 18 2.3 std标准命名空间 20 2.4 C++新增的标准输入输出方法(cin和cout) 22 2.5 C++规定的变量定义位置 24 2.6 C++新增的布尔类型(bool) 24 2.7 C++ 新增的new和delete运算符 25 2.8 C++函数的默认参数(缺省参数) 26 2.9 C++函数重载详解 28 2.10 C++新增的引用语法 30 三、 C++面向对象:类和对象 34 3.1 类的定义和对象的创建 34 3.2 类的成员变量和成员函数 36 3.3 类成员的访问权限以及类的封装 38 3.4 C++类的构造函数与析构函数 39 3.5 对象数组 47 3.6 this指针 50 3.7 static静态成员变量 52 3.8 static静态成员函数 53 3.9 const成员变量和成员函数 55 3.10 const对象(常对象) 56 3.11 友元函数和友元类 58 3.11.3 友元类 61 3.12 C++字符串 62 四、C++面向对象:继承与派生 75 4.1 继承与派生概念介绍 75 4.2 继承的语法介绍 75 4.3 继承方式介绍(继承的权限) 76 4.4 继承时变量与函数名字遮蔽问题 79 4.5 基类和派生类的构造函数 82 4.6 基类和派生类的析构函数 83 4.7 多继承 85 4.8 虚继承和虚基类 88 五、C++多态与抽象类 91 5.1 多态概念介绍 91 5.2 虚函数 92 5.3 纯虚函数和抽象类 95 六、C++运算符重载 97 6.1 运算符重载语法介绍 97 6.2 可重载运算符与不可重载运算符 98 6.3 一元运算符重载 99 6.4 二元运算符重载 102 6.5 关系运算符重载 104 6.6 输入/输出运算符重载(>>、<<) 105 6.7 函数调用运算符 () 重载 106 6.8 重载[ ](下标运算符) 107 七、C++模板和泛型程序设计 108 7.1 函数模板 108 7.2 类模板 110
目录 第1章 基本类型 1.1 一个例程 1.2 类型与声明 1.3 基本类型 1.3.1 整数类型 1.3.2 字符类型 1.3.3 浮点类型 1.3.4 布尔类型 1.3.5 void类型 1.4 数值极限 1.5 标识符和关键词 1.5.1 标识符 1.5.2 关键词 1.6 练习 第2章 表达式和语句 2.1 作用域和存储分类 2.1.1 局部变量和全局变量 2.1.2 外部变量和寄存器变量 2.2 表达式 2.2.1 算术表达式 .2.2.2 关系表达式 2.2.3 逻辑表达式 2.2.4 位运算表达式 2.2.5 逗号表达式 2.3 语句 2.3.1 声明和初始化 2.3.2 赋值语句 2.3.3 复合赋值语句 2.3.4 增值减值语句 2.3.5 复合语句 2.3.6 条件语句 2.3.7 循环语句 2.4 斐波纳契数 2.5 练习 第3章派生类型 3.1 常量和宏 3.2 枚举类型 3.3 数组 3.4 结构 3.5 联合和比特域 3.6 指针 3.6.1 指针运算 3.6.2 多重指针 3.6.3 偏移量指针 3.6.4 常量指针 3.6.5 void指针和空指针 3.6.6 结构指针 3.6.7 字符指针 3.6.8 指针和数组 3.7 引用 3.8 函数 3.8.1 函数声明和定义 3.8.2 函数重载 3.8.3 参数传递 3.8.4 返回值 3.8.5 递归函数 3.8.6 内联函数 3.8.7 缺省参数 3.8.8 函数类型 3.8.9 静态局部变量 3.8.10 main函数 3.9 程序的运行空间 3.10 运算符概要及优先级 3.11 标准数学函数库 3.12 多项式求值 3.13 梯形公式和simpson公式 3.14 练习 第4章 命名空间和文件 4.1 命名空间 4.1.1 使用声明和指令 4.1.2 多重接口 4.1.3 命名空间别名 4.1.4 无名命名空间 4.1.5 名称查找 4.2 包含文件 4.2.1 包含标准库文件 4.2.2 用户自定义头文 4.2.3 条件包含指令 4.2.4 文件包含 4.3 源文件和连接 4.3.1 独立编译 4.3.2 外部连接和内部连接 4.3.3 与其他语言连接 4.4 一些有用的工具 4.4.1 给程序计时的方法 4.4.2 编译选项和调试器 4.4.3 创建库 4.4.4 makefile 4.5 字符串标准函数库 4.5.1 声明和初始化 4.5.2 操作 4.5.3 c语言字符串 4.5.4 输入输出 4.5.5 c字符串函数库 4.6 流标准函数库 4.6.1 整数格式化输出 4.6.2 浮点数格式化输出 4.6.3 输出宽度 4.6.4 文件的输入输出 4.6.5 字符的输入输出 4.6.6 字符串流 4.7 非线性方程的迭代解法 4.7.1 二分法 4.7.2 牛顿法 4.8 练习 第5章 类 5.1 类的声明与定义 5.2 拷贝构造函数和拷贝赋值 5.3 友元 5.4 静态成员 5.5 常量和可变成员 5.6 类的对象作为成员 5.7 类的数组 5.8 成员指针 5.9 常微分方程的数值解法 5.10 练习 第6章 运算符重载 6.1 复数 6.1.1 初始化 6.1.2 缺省拷贝构造和赋值 6.1.3 转换和混合模式运算 6.2 运算符函数 6.3 向量和矩阵 6.4 显式和隐式类型转换 6.5 效率和运算符重载 6.6 共扼梯度算法 6.7 练习 第7章 模板 7.1 类模板 7.1.1 成员和友元定义 7.1.2 模板实例化 7.1.3 模板参数 7.1.4 类型等价 7.1.5 用户定义的特化 7.1.6 特化顺序 7.2 函数模板 7.2.1 函数模板参数 7.2.2 函数模板重载 7.2.3 特化 7.2.4 类模板作为函数模板参数 7.2.5 成员函数模板 7.2.6 友元函数模板 7.3 模板源代码组织 7.4 标准复数库 7.5 标准ualarray库 7.5.1 ualarray类型 7.5.2 分段数组 7.5.3 广义分段数组 7.5.4 掩码数组和间接数组 7.6 数值算法标准函数库 7.6.1 累加 7.6.2 内积 7.6.3 部分和 7.6.4 临近差分 7.7 数值积分的高效技术 7.7.1 函数对象方法 7.7.2 函数指针作为模板参数 7.7.3 使用点积和模板表达式 7.7.4 采用点积和模板元程序 7.8 多项式插值 7.8.1 拉格朗日形式 7.8.2 牛顿形式 7.9 练习 第8章 类的继承 8.1 派生类 8.1.1 成员函数 8.1.2 构造函数和析构函数 8.1.3 拷贝 8.1.4 类层次结构 8.1.5 虚函数 8.1.6 虚析构函数 8.2 抽象类 8.3 访问控制 8.3.1 访问成员 8.3.2 基类访问 8.4 多重继承 8.4.1 去除二义性 8.4.2 重复基类 8.4.3 虚基类 8.4.4 多重继承中的访问控制 8.5 运行时的类型信息 8.5.1 动态投影机制 8.5.2 类型标识机制 8.5.3 运行时负担 8.6 用静态多态代替虚函数 8.7 练习 第9章 异常处理 9.1 抛出和捕获 9.2 派生异常 9.3 捕获异常 9.3.1 重抛出 9.3.2 捕获所有异常 9.3.3 处理函数的顺序 9.4 在函数中指定异常 9.5 标准异常 9.6 练习 第10章 容器和算法标准库 10 标准容器 10.1 向量 10.2 链表 10.1.3 映射与集合 10.1.4 栈和队列 10.2 标准算法 10.2.1 排序、复制和替换算法 10.2.2 搜索和遍历算法 10.2.3 集合、排列和堆算法 10.3 标准函数对象和适配器 10.3.1 算术函数对象 1o.3.2 关系函数对象 10.3.3 逻辑函数对象 10.3.4 标准适配器 10.4 练习 第11章 线性方程组求解法 11.1 矩阵存储格式 11.1.1 满矩阵 11.1.2 带状矩阵 11.1.3 稀疏矩阵 11.2 矩阵类层次 11.3 迭代算法 11.3.1 共轭梯度方法 11.3.2 广义最小残差法 11.3.3 预处理技术 11.4 高斯消元法 11.4.1 lu分解 11.4.2 高斯消元法 11.4.3 主元高斯消元法 11.5 求解偏微分方程的有限差分方法 11.6 练习 参考文献

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧