这几天疫情在家闲来无聊,翻开许久没看的STL开始复读起来。
mem_fun_ref这个函数印象很深。
属于function adapter。
最常见的用法:
#include <iostream>
#include <vector>
#include <deque>
#include <iterator>
#include <algorithm>
using namespace std;
class base
{
public:
virtual void dosomething()
{
}
virtual void donextthing()
{
}
};
class Int : public base
{
public:
Int(int i)
: mI(i)
{
}
virtual void dosomething()
{
cout << "i等于" << mI << endl;
}
void print() const
{
cout << "第" << count++ << "个数是" << mI << endl;
}
private:
static int count;
int mI;
};
int Int::count = 0;
void main()
{
int arr[10] = {0,1,2,3,4,5,6,7,8,9};
vector<int> vec(arr,arr+10);
for_each(vec.begin(),vec.end(),mem_fun_ref(&Int::print));
Int* i = new Int(3);
Int j(5);
cout << "j的大小为:"<< sizeof(j) << endl;
printf("address of base::dosomething %x\n", &base::dosomething);
printf("address of derived::dosomething %x\n", &Int::dosomething);
printf("address of derived::donextthing %x\n", &Int::donextthing);
printf("address of derived::print%x\n", &Int::print);
void(__thiscall Int::* f)(void) = &base::dosomething;
(i->*f)();//->*的用法,经由对象指针调用
(j.*f)(); //.*的用法,经由对象调用
}
依次输出容器内的各个对象。
那这到底是怎么实现的呢?
我们给mem_fun_ref传入了函数的地址,这个是Int,派生类的地址。
妈的语言组织能力太差,直接上图,一切尽在不言中
也就是说父类和子类的虚函数的地址是一样的,一个函数占4个字节的内存,并且虚函数都是连续的地址,这样子类就只需要存一个虚函数表和一个偏移就行了,调用的时候才用__thiscall机制,传入this指针,找到其虚函数表,再调用!