对c++友元函数和友元类的理解
2016-06-26 20:44
429 查看
1,友元函数的定义和作用
我们已知道类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。
为了解决上述问题,提出一种使用友元的方案。友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率(即减少了类型检查和安全性检查等都需要的时间开销),但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。
2,上述的访问不是直接访问,对于普通私有成员变量是通过对象访问,对于私有静态变量是通过类访问。
为什么不能直接访问呢?
先了解一下为什么成员函数可以直接访问成员变量?
成员函数能够访问类的成员变量是因为传递了指向当前对象的this指针,它如果访问数据成员对其操作是this指向的对象的数据成员,是有实际意义的 。
友元函数不是成员函数,没有传递隐藏的this指针,只能间接访问。
这点其实和静态成员函数一样,静态成员函数也是没有this指针的,所以它只能访问静态成员变量或者通过对象访问非静态成员变量。
例子:
下边转载自:
http://blog.csdn.net/shandianling/article/details/7469361
C++ Primer中有如下描述:友元关系不能继承。基类的友元对派生类的成员没有特殊访问
权限。如果基类被授予友元关系,则只有基类具有特殊访问权限,该基类的派生类不能访问授予友元关系的类。
然而通过实践发现,VS编译器并没有安装上述描述来处理,下面的规则与上述描述相悖,却符合VS编译器的处理规则。
注:有待通过g++编译器来验证。
1 友元类的继承问题
1.1 A类的友元B的派生类C 不能访问A类的private或protect成员变量。但可以通过B提供的接口来访问A。(废话肯定可以)
[cpp] view
plain copy
#include <iostream>
using namespace std;
class B;
class A
{
int a;
public:
A(int x=0) { a=x; }
friend class B;
};
class B
{
int b;
public:
void fun(A& ob){ cout << ob.a << endl;}
};
class C:public B
{
public:
//void fun2(A& ob){ cout <<ob.a <<endl;} //派生类新加的函数却不能访问A,此句会报错
};
void main()
{
A a(55);
C c;
c.fun(a); //C是B的派生类 通过基类B的函数fun仍然可以访问
}
1.2. Base的友元可以通过Base的派生类Drived访问Base的private,protect成员变量,但不能访问Drived的private,protect成员变量。(这一点似乎与《C++ primer》里说的有点冲突)
个人理解:Drived的对象本身就包含Base,Base的友元Frnd自然就可以访问Base的部分。
[cpp] view
plain copy
#include <iostream>
using namespace std;
class Base
{
int m_a;
public:
Base(int x=0){ m_a=x; }
friend class Frnd;
};
class Drived:public Base
{
private:
int m_c;
public:
Drived(int x):Base(x){m_c=x;}
};
class Frnd
{
public:
void fun(Base& ob) { cout <<ob.m_a << endl; }
void fun2(Drived& ob)
{
cout << ob.m_a<<endl;
//cout <<ob.m_c<<endl; //编译错误
}
};
int main()
{
Drived d(1);
Frnd f;
f.fun(d);
f.fun2(d);
system("pause");
return 0;
}
3 友元类的传递问题
A的友元是B,B的友元是C,那A的友元是C? 不是,友元类不具有传递性。
我们已知道类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。
为了解决上述问题,提出一种使用友元的方案。友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率(即减少了类型检查和安全性检查等都需要的时间开销),但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。
2,上述的访问不是直接访问,对于普通私有成员变量是通过对象访问,对于私有静态变量是通过类访问。
为什么不能直接访问呢?
先了解一下为什么成员函数可以直接访问成员变量?
成员函数能够访问类的成员变量是因为传递了指向当前对象的this指针,它如果访问数据成员对其操作是this指向的对象的数据成员,是有实际意义的 。
友元函数不是成员函数,没有传递隐藏的this指针,只能间接访问。
这点其实和静态成员函数一样,静态成员函数也是没有this指针的,所以它只能访问静态成员变量或者通过对象访问非静态成员变量。
例子:
class Rect { public: Rect() // 构造函数,计数器加1 { count++; } //Rect(const Rect& r) //{ // width = r.width; // height = r.height; // count++; //} ~Rect() // 析构函数,计数器减1 { count--; } static int getCount() // 返回计数器的值 { return count; } friend int get(); private: int width; int height; static int count; // 一静态成员做为计数器 }; int Rect::count = 0; // 初始化计数器 int get() { return Rect::count;//友元函数通过类访问私有静态成员变量 } int main() { Rect rect1; cout<<"The count of Rect: "<<Rect::getCount()<<endl;//通过类访问公有静态成员函数,输出1 Rect rect2(rect1); // 使用rect1复制rect2,此时应该有两个对象 cout<<"The count of Rect: "<<Rect::getCount()<<endl; //输出1 cout << get() << endl;//输出1 //cout << Rect::count << endl;//不能编译通过,不能访问私有成员 system("pause"); return 0; }3,类和类之间的友元关系不能继承。
下边转载自:
http://blog.csdn.net/shandianling/article/details/7469361
C++ Primer中有如下描述:友元关系不能继承。基类的友元对派生类的成员没有特殊访问
权限。如果基类被授予友元关系,则只有基类具有特殊访问权限,该基类的派生类不能访问授予友元关系的类。
然而通过实践发现,VS编译器并没有安装上述描述来处理,下面的规则与上述描述相悖,却符合VS编译器的处理规则。
注:有待通过g++编译器来验证。
1 友元类的继承问题
1.1 A类的友元B的派生类C 不能访问A类的private或protect成员变量。但可以通过B提供的接口来访问A。(废话肯定可以)
[cpp] view
plain copy
#include <iostream>
using namespace std;
class B;
class A
{
int a;
public:
A(int x=0) { a=x; }
friend class B;
};
class B
{
int b;
public:
void fun(A& ob){ cout << ob.a << endl;}
};
class C:public B
{
public:
//void fun2(A& ob){ cout <<ob.a <<endl;} //派生类新加的函数却不能访问A,此句会报错
};
void main()
{
A a(55);
C c;
c.fun(a); //C是B的派生类 通过基类B的函数fun仍然可以访问
}
1.2. Base的友元可以通过Base的派生类Drived访问Base的private,protect成员变量,但不能访问Drived的private,protect成员变量。(这一点似乎与《C++ primer》里说的有点冲突)
个人理解:Drived的对象本身就包含Base,Base的友元Frnd自然就可以访问Base的部分。
[cpp] view
plain copy
#include <iostream>
using namespace std;
class Base
{
int m_a;
public:
Base(int x=0){ m_a=x; }
friend class Frnd;
};
class Drived:public Base
{
private:
int m_c;
public:
Drived(int x):Base(x){m_c=x;}
};
class Frnd
{
public:
void fun(Base& ob) { cout <<ob.m_a << endl; }
void fun2(Drived& ob)
{
cout << ob.m_a<<endl;
//cout <<ob.m_c<<endl; //编译错误
}
};
int main()
{
Drived d(1);
Frnd f;
f.fun(d);
f.fun2(d);
system("pause");
return 0;
}
3 友元类的传递问题
A的友元是B,B的友元是C,那A的友元是C? 不是,友元类不具有传递性。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- PostgreSQL教程(三):表的继承和分区表详解
- Lua中调用C++函数示例
- Lua面向对象之类和继承浅析
- Lua教程(一):在C++中嵌入Lua脚本
- 浅析Ruby中继承和消息的相关知识
- Lua教程(二):C++和Lua相互传递数据示例
- 设计引导--一个鸭子游戏引发的设计理念(多态,继承,抽象,接口,策略者模式)
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法