bind和多态
来源:互联网 发布:淘宝隐形眼镜可靠吗 编辑:程序博客网 时间:2024/06/11 17:22
定义一个函数为虚函数,不代表函数为不被实现的函数,定义它为虚函数是为了允许用基类的指针来调用子类的这个函数
定义一个函数为纯虚函数,才代表函数没有被实现,定义他是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
===================================================>
C++支持两种多态性:编译时多态性,运行时多态性。
a、编译时多态性:通过重载函数实现
b、运行时多态性:通过虚函数实现。
C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同,即函数的参数列表不同,也就是说用同一个运算符完成不同的运算功能。这就是重载函数C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同,即函数的参数列表不同,也就是说用同一个运算符完成不同的运算功能。这就是重载函数
C++用虚函数实现多态
父类里定义了虚函数
子类重写虚函数
========================================================》》》》
C++深入理解虚函数
面向对象的三大特征:
封装++++多态++++++继承
1,普通虚函数
2,虚析够函数
3,纯虚函数
4,抽象类
5,接口类
6,隐藏VS覆盖
7,隐藏与覆盖之间的关系
8,早绑定和晚绑定
9,虚函数表
什么是多态:
静态多态VS动态多态
a,静态多态也叫做早绑定:他们函数名相同,参数个数不同,一看就是互为重载的两个函数
b,动态多态也叫做晚绑定:可见动态多态是以封装和继承为基础的
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
virtual在函数中的使用规则:
1,普通函数不能是虚函数,也就是说这个函数必须是某一个类的成员函数,
不可以是一个全局函数,否则会导致编译错误
2,静态函数不能是虚函数,static成员函数是和类同生共处的,他不属于任何
对象,使用virtual也将导致错误
3,内联函数不能是虚函数,如果修饰内联函数,如果内联函数被virtual修饰,
计算机会忽略inline使他变成纯粹的虚函数
4,构造函数不能是虚函数,否则会出现编译错误
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
什么是函数指针
指针指向对象称为对象指针,指针除了指向对象还可以指向函数。
函数的指针和普通的指针本质是一样的,也是由四个基本的内存单元组成,
存储着内存的地址,这个地址就是函数的首地址。
多态的实现原理:
虚函数表指针:类中除了定义的函数成员,还有一个成员是虚函数表指针
(占4个基本内存单元),这个指针指向一个虚函数表的起始位置,这个类会与
类的定义同时出现,这个表存放着该类的虚函数指针,调用的时候可以找到
该类的虚函数表指针,通过虚函数表指针找到虚函数表,通过虚函数表的偏移
找到函数的入口地址,这个地址就是函数的首地址
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
函数的覆盖和隐藏
父类和子类出现同名函数称为隐藏
父类对象.函数函数名(...); //调用父类的函数
子类对象.函数名(...); //调用子类的函数
子类对象.父类名::函数名(...);//子类调用从父类继承来的函数。
父类和子类出现同名虚函数称为覆盖
父类指针=new 子类名(...);父类指针->函数名(...);//调用子类的虚函数。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
虚析构函数的实现原理
虚析构函数的特点
当我们在父类中通过virtual修饰析构函数之后,通过父类指针指向子类对象,
通过delete接父类指针就可以释放掉子类对象
执行完子类的析构函数就会执行父类的析构函数
原理:
如果父类当中定义了虚析构函数,那么父类的虚函数表当中就会有一个父类的
虚析构函数的入口指针,指向的是父类的虚析构函数,子类虚函数表当中也会
产生一个子类的虚析构函数的入口指针,指向的是子类的虚析构函数,这个时候
使用父类的指针指向子类的对象,delete接父类指针,就会通过指向的子类的对象
找到子类的虚函数表指针,从而找到虚函数表,再虚函数表中找到子类的虚析构函数
,从而使得子类的析构函数得以执行,子类的析构函数执行之后系统会自动执行父类
的虚析构函数。这个是虚析构函数的实现原理。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
含有纯虚函数的类被称为抽象类
不支持C++11的编译器。
boost库里面最值得使用的是bind,function,shared_ptr等
在c++11之前,要绑定某个函数、函数对象或者成员函数的不同参数
值需要用到不同的转换器,如bind1st、bind2nd、fun_ptr、mem_fun和
mem_fun_ref等.在c++11中,绑定参数的方法得以简化.c++11提供了"一站
式"绑定模板bind,其用法为:
#include <functional>
std::bind(待绑定的函数对象/函数指针/成员函数指针,参数绑定值1,参数绑定值2,...,参数绑定值n);
bind的第一个参数是待绑定的函数对象或者函数指针,之后跟随多个参数以设定
待绑定函数的参数绑定方式。待绑定函数有多少个参数,则bind后便需要多少个
参数以一一声明其参数的绑定方法 ,当参数绑定为某一固定值时,则其对应
参数绑定值可以使一个一个变量或常量。当需要将参数与绑定所生成的函数对象的
某个参数相关联,则需要用到标准中预定义的几个常量_1、_2、_3等,这些常量
声明在std::placeholders命名空间内
绑定成员函数的注意点:
在将一个R (T::*ptr)(Arg0,Arg1,...)形式的成员函数指针ptr用bind绑定
参数时,bind的第一个绑定的参数是成员函数的调用者,随后跟随成员函数
的参数绑定方式,例如bind(ptr,a,b,c)将会调用a.*ptr(b,c)。当采用
_n常量将首参数与函数对象的参数相关联时,所生成的函数对象自动可接受
T类型的引用及指针类型,无需在进行封装,但要想调用外部数据的成员函数,
还需要ref(),cref()来包装或者绑定一个对该变量的指针
#include <functional>
#include <iostream>
//一个自定义的整数类
struct integer{
int i;
integer(int i):i(i){}
void incr_by(int j){ i+=j;}
};
void mem_func_sample(){
integer x(0); //x.i=0;
integer *y=&x; //y指向x
using namespace std::placeholders;
using namespace std;
auto f0=bind(&integer::incr_by,_1,_2);
f0(x,2); //x.incr_by(2)
cout<<x.i<<endl;
f0(y,2); //y->incr_by(2)
cout<<x.i<<endl; //x.i=4
auto f1=bind(&integer::incr_by,x,_1);
f1(2); //x在f1的副本.incr(2)
cout<<x.i<<endl; x.i=4;
auto f2=bind(&integer::ince_by,ref(x),_1);
f2(2); //x.incr_by(2)
cout<<x.i<<endl; //x.i=6;
auto f3=bind(&integer::incr_by,&x,_1);
f3(2); //(&x)->incr_by(2)
cout<<x.i<<endl; //x.i=8
//利用mem_fn将成员函数转换为函数对象
auto f4=mem_fn(&integer::incr_by);
f4(x,2);
cout<<x.i<<endl;//x.i=10;
f4(y,2);
cout<<x.i<<endl;//x.i=12
}
上例中用不同的方式为integer类的incr_by成员函数绑定参数.
对于所得的函数对象f0,由于bind的首参数与f0的第一个参数相
关联,f0将自动以integer为首参数类型,所以f0(x,2)实际调用
了x.incr_by(2),使得x的i值增加2;另外f0也自动支持integr指针,
所以调用f0(y,2)相等于执行了y->incr_by(2),同样使得x的i值增加2。
而f1的调用是x在f1内的副本,不会影响x的状态.只有如f2或f3那样绑
定x才会真正调用x的成员函数.
定义一个函数为纯虚函数,才代表函数没有被实现,定义他是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
===================================================>
C++支持两种多态性:编译时多态性,运行时多态性。
a、编译时多态性:通过重载函数实现
b、运行时多态性:通过虚函数实现。
C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同,即函数的参数列表不同,也就是说用同一个运算符完成不同的运算功能。这就是重载函数C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同,即函数的参数列表不同,也就是说用同一个运算符完成不同的运算功能。这就是重载函数
C++用虚函数实现多态
父类里定义了虚函数
子类重写虚函数
========================================================》》》》
C++深入理解虚函数
面向对象的三大特征:
封装++++多态++++++继承
1,普通虚函数
2,虚析够函数
3,纯虚函数
4,抽象类
5,接口类
6,隐藏VS覆盖
7,隐藏与覆盖之间的关系
8,早绑定和晚绑定
9,虚函数表
什么是多态:
静态多态VS动态多态
a,静态多态也叫做早绑定:他们函数名相同,参数个数不同,一看就是互为重载的两个函数
b,动态多态也叫做晚绑定:可见动态多态是以封装和继承为基础的
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
virtual在函数中的使用规则:
1,普通函数不能是虚函数,也就是说这个函数必须是某一个类的成员函数,
不可以是一个全局函数,否则会导致编译错误
2,静态函数不能是虚函数,static成员函数是和类同生共处的,他不属于任何
对象,使用virtual也将导致错误
3,内联函数不能是虚函数,如果修饰内联函数,如果内联函数被virtual修饰,
计算机会忽略inline使他变成纯粹的虚函数
4,构造函数不能是虚函数,否则会出现编译错误
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
什么是函数指针
指针指向对象称为对象指针,指针除了指向对象还可以指向函数。
函数的指针和普通的指针本质是一样的,也是由四个基本的内存单元组成,
存储着内存的地址,这个地址就是函数的首地址。
多态的实现原理:
虚函数表指针:类中除了定义的函数成员,还有一个成员是虚函数表指针
(占4个基本内存单元),这个指针指向一个虚函数表的起始位置,这个类会与
类的定义同时出现,这个表存放着该类的虚函数指针,调用的时候可以找到
该类的虚函数表指针,通过虚函数表指针找到虚函数表,通过虚函数表的偏移
找到函数的入口地址,这个地址就是函数的首地址
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
函数的覆盖和隐藏
父类和子类出现同名函数称为隐藏
父类对象.函数函数名(...); //调用父类的函数
子类对象.函数名(...); //调用子类的函数
子类对象.父类名::函数名(...);//子类调用从父类继承来的函数。
父类和子类出现同名虚函数称为覆盖
父类指针=new 子类名(...);父类指针->函数名(...);//调用子类的虚函数。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
虚析构函数的实现原理
虚析构函数的特点
当我们在父类中通过virtual修饰析构函数之后,通过父类指针指向子类对象,
通过delete接父类指针就可以释放掉子类对象
执行完子类的析构函数就会执行父类的析构函数
原理:
如果父类当中定义了虚析构函数,那么父类的虚函数表当中就会有一个父类的
虚析构函数的入口指针,指向的是父类的虚析构函数,子类虚函数表当中也会
产生一个子类的虚析构函数的入口指针,指向的是子类的虚析构函数,这个时候
使用父类的指针指向子类的对象,delete接父类指针,就会通过指向的子类的对象
找到子类的虚函数表指针,从而找到虚函数表,再虚函数表中找到子类的虚析构函数
,从而使得子类的析构函数得以执行,子类的析构函数执行之后系统会自动执行父类
的虚析构函数。这个是虚析构函数的实现原理。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
含有纯虚函数的类被称为抽象类
不支持C++11的编译器。
boost库里面最值得使用的是bind,function,shared_ptr等
在c++11之前,要绑定某个函数、函数对象或者成员函数的不同参数
值需要用到不同的转换器,如bind1st、bind2nd、fun_ptr、mem_fun和
mem_fun_ref等.在c++11中,绑定参数的方法得以简化.c++11提供了"一站
式"绑定模板bind,其用法为:
#include <functional>
std::bind(待绑定的函数对象/函数指针/成员函数指针,参数绑定值1,参数绑定值2,...,参数绑定值n);
bind的第一个参数是待绑定的函数对象或者函数指针,之后跟随多个参数以设定
待绑定函数的参数绑定方式。待绑定函数有多少个参数,则bind后便需要多少个
参数以一一声明其参数的绑定方法 ,当参数绑定为某一固定值时,则其对应
参数绑定值可以使一个一个变量或常量。当需要将参数与绑定所生成的函数对象的
某个参数相关联,则需要用到标准中预定义的几个常量_1、_2、_3等,这些常量
声明在std::placeholders命名空间内
绑定成员函数的注意点:
在将一个R (T::*ptr)(Arg0,Arg1,...)形式的成员函数指针ptr用bind绑定
参数时,bind的第一个绑定的参数是成员函数的调用者,随后跟随成员函数
的参数绑定方式,例如bind(ptr,a,b,c)将会调用a.*ptr(b,c)。当采用
_n常量将首参数与函数对象的参数相关联时,所生成的函数对象自动可接受
T类型的引用及指针类型,无需在进行封装,但要想调用外部数据的成员函数,
还需要ref(),cref()来包装或者绑定一个对该变量的指针
#include <functional>
#include <iostream>
//一个自定义的整数类
struct integer{
int i;
integer(int i):i(i){}
void incr_by(int j){ i+=j;}
};
void mem_func_sample(){
integer x(0); //x.i=0;
integer *y=&x; //y指向x
using namespace std::placeholders;
using namespace std;
auto f0=bind(&integer::incr_by,_1,_2);
f0(x,2); //x.incr_by(2)
cout<<x.i<<endl;
f0(y,2); //y->incr_by(2)
cout<<x.i<<endl; //x.i=4
auto f1=bind(&integer::incr_by,x,_1);
f1(2); //x在f1的副本.incr(2)
cout<<x.i<<endl; x.i=4;
auto f2=bind(&integer::ince_by,ref(x),_1);
f2(2); //x.incr_by(2)
cout<<x.i<<endl; //x.i=6;
auto f3=bind(&integer::incr_by,&x,_1);
f3(2); //(&x)->incr_by(2)
cout<<x.i<<endl; //x.i=8
//利用mem_fn将成员函数转换为函数对象
auto f4=mem_fn(&integer::incr_by);
f4(x,2);
cout<<x.i<<endl;//x.i=10;
f4(y,2);
cout<<x.i<<endl;//x.i=12
}
上例中用不同的方式为integer类的incr_by成员函数绑定参数.
对于所得的函数对象f0,由于bind的首参数与f0的第一个参数相
关联,f0将自动以integer为首参数类型,所以f0(x,2)实际调用
了x.incr_by(2),使得x的i值增加2;另外f0也自动支持integr指针,
所以调用f0(y,2)相等于执行了y->incr_by(2),同样使得x的i值增加2。
而f1的调用是x在f1内的副本,不会影响x的状态.只有如f2或f3那样绑
定x才会真正调用x的成员函数.
阅读全文
0 0
- bind和多态
- bind安装,rndc和bind升级
- Eval和Bind
- eval()和bind()
- Eval()和Bind()
- bind 和live
- Eval 和bind区别
- connect和bind
- bind编译和配置
- Eval和Bind
- Bind 和 ScaffoldColumn
- DNS和BIND
- DNS和bind
- bind和new
- Eval和Bind的区别
- Eval和Bind的区别
- Bind和eval的区别
- Eval和Bind的区别
- 搭建zookeeper伪集群
- pycharm配置
- HTML中超链接原来还有这种操作??
- 自组织特征映射SOM(Self-organizing feature Map)
- Android基础:Fragment
- bind和多态
- Spring 解析xml代码提取
- 汉诺塔
- 第一章 离散时间信号与系统
- Head First Python 第一章 看书心得
- 3.1
- python基础-类内置函数、类内置方法
- Docker技术入门与实战+第2版.pdf 免费下载
- ESP8266 ESP01 Arduino IDE 烧录配置