c++程序设计笔记(4)
2016-03-08 16:04
218 查看
友元(Friend):
友元函数和友元类
友元函数:
1、一个类的友元函数可以访问该类的私有成员
class A{
int a;
public:
A(int a1){
a = a1;
}
friend void func(A a);
};
void func(A a){
cout<<a.a<<endl;
}
int main() {
A a(2);
func(a);
return 0;
}
2、一个类的成员函数(包括构造、析构函数)定义为另一个类的友元。访问非静态私有变量把A的对象作为形参
class B{ //A中要用到B的类型,所以要在之前对B进行声明。此处也体现出了.h和.cpp文件分离开的好处
public:
void func();
};
class A{
static int b;
friend void B::func();
};
int A::b = 9;
void B::func(){
cout<<A::b<<endl;
}
int main() {
B b;
b.func();
return 0;
}
友元类:
友元类不能传递!不能继承!
A是B的友元类,B的成员函数可以访问A的私有成员(静态,非静态,非静态多加一个形参)
class A{
static int b;
friend class B;
};
int A::b = 9;
class B{
public:
void func(){
cout<<A::b<<endl;
}
};
int main() {
B b;
b.func();
return 0;
}
this指针:
指向成员函数所作用的对象。
空指针也可以访问成员函数。
class A {
int a;
public:
void func(){//编译时会多一个参数func(A* this)
cout<<"come to A func"<<endl;
}
void func2(){
cout<<"come to A func2:"<<this->a<<endl;
}
};
int main() {
A *p = NULL;
p->func();//可以调用
p->func2();//运行错误
return 0;
}
为什么空指针可以访问成员函数?知乎里有两个比较好的回答:
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:Damien
链接:http://www.zhihu.com/question/23260677/answer/33165965
来源:知乎
和c++内存布局有关,为了节约内存和提高调用效率,一般类成员的存储分成两块,一块是单个instance所有,比如非静态成员变量,另一块是所有instances共享的,比如函数代码。这样的布局是对于性能有好处的,代码只要load一次,减少了cache占用和miss。如果你的函数不引用任何instance独有的内存部分,nullptr并无问题,因为不会使用this,只会使用类instance共享的部分,这部分始终存在,即使你没有任何类实例。反之就会出问题,因为你试图访问不存在的数据
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:张景旺
链接:http://www.zhihu.com/question/23260677/answer/24081527
来源:知乎
但是对于C++。为了保证程序的运行时效率,C++的设计者认为凡是编译时能确定的事情,就不要拖到运行时再查找了。所以C++的编译器看到这句话会这么干:
1:查找somenull的类型,发现它有一个非虚的成员函数叫foo。(编译器干的)
2:找到了,在这里生成一个函数调用,直接调B::foo(somenull)。
所以到了运行时,由于foo()函数里面并没有任何需要解引用somenull指针的代码,所以真实情况下也不会引发segment fault。这里对成员函数的解析,和查找其对应的代码的工作都是在编译阶段完成而非运行时完成的,这就是所谓的静态绑定,也叫早绑定。
正确理解C++的静态绑定可以理解一些特殊情况下C++的行为。
友元函数和友元类
友元函数:
1、一个类的友元函数可以访问该类的私有成员
class A{
int a;
public:
A(int a1){
a = a1;
}
friend void func(A a);
};
void func(A a){
cout<<a.a<<endl;
}
int main() {
A a(2);
func(a);
return 0;
}
2、一个类的成员函数(包括构造、析构函数)定义为另一个类的友元。访问非静态私有变量把A的对象作为形参
class B{ //A中要用到B的类型,所以要在之前对B进行声明。此处也体现出了.h和.cpp文件分离开的好处
public:
void func();
};
class A{
static int b;
friend void B::func();
};
int A::b = 9;
void B::func(){
cout<<A::b<<endl;
}
int main() {
B b;
b.func();
return 0;
}
友元类:
友元类不能传递!不能继承!
A是B的友元类,B的成员函数可以访问A的私有成员(静态,非静态,非静态多加一个形参)
class A{
static int b;
friend class B;
};
int A::b = 9;
class B{
public:
void func(){
cout<<A::b<<endl;
}
};
int main() {
B b;
b.func();
return 0;
}
this指针:
指向成员函数所作用的对象。
空指针也可以访问成员函数。
class A {
int a;
public:
void func(){//编译时会多一个参数func(A* this)
cout<<"come to A func"<<endl;
}
void func2(){
cout<<"come to A func2:"<<this->a<<endl;
}
};
int main() {
A *p = NULL;
p->func();//可以调用
p->func2();//运行错误
return 0;
}
为什么空指针可以访问成员函数?知乎里有两个比较好的回答:
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:Damien
链接:http://www.zhihu.com/question/23260677/answer/33165965
来源:知乎
和c++内存布局有关,为了节约内存和提高调用效率,一般类成员的存储分成两块,一块是单个instance所有,比如非静态成员变量,另一块是所有instances共享的,比如函数代码。这样的布局是对于性能有好处的,代码只要load一次,减少了cache占用和miss。如果你的函数不引用任何instance独有的内存部分,nullptr并无问题,因为不会使用this,只会使用类instance共享的部分,这部分始终存在,即使你没有任何类实例。反之就会出问题,因为你试图访问不存在的数据
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:张景旺
链接:http://www.zhihu.com/question/23260677/answer/24081527
来源:知乎
但是对于C++。为了保证程序的运行时效率,C++的设计者认为凡是编译时能确定的事情,就不要拖到运行时再查找了。所以C++的编译器看到这句话会这么干:
1:查找somenull的类型,发现它有一个非虚的成员函数叫foo。(编译器干的)
2:找到了,在这里生成一个函数调用,直接调B::foo(somenull)。
所以到了运行时,由于foo()函数里面并没有任何需要解引用somenull指针的代码,所以真实情况下也不会引发segment fault。这里对成员函数的解析,和查找其对应的代码的工作都是在编译阶段完成而非运行时完成的,这就是所谓的静态绑定,也叫早绑定。
正确理解C++的静态绑定可以理解一些特殊情况下C++的行为。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- 解析C++中派生的概念以及派生类成员的访问属性