1、函数重载的回顾
1.1、函数重载的
本质
为互相独立的
不同函数
。
1.2、C++中通过
函数名
和
函数参数
确定函数调用,函数名和参数列表
组成唯一的标识
。
1.3、无法直接通过
函数名
得到重载函数的入口地址。
1.4、函数重载必然发生在
同一个作用域
中。
/********* 类成员函数指针(类成员函数的函数指针) *******/
#include <iostream>
using namespace std;
class Test
{
public :
void show()
{
cout << "Test::show()" << endl;
}
void print()
{
cout << "Test::print()" << endl;
}
};
//声明类成员函数指针
typedef void (Test::*PFunc)(); //PFunc 表示 void (Test:: *)()这个类的成员函数指针。
int main()
{
Test t;
PFunc p = &Test::show; //将指针函数p指向 show()这个函数。函数名表示地址。
(t.*p)(); //Test::show
//类型不匹配???
p = &Test::print;
(t.*p)(); //Test::print
return 0;
}
/*** C++中如何获取类的成员函数的函数指针? **/
#include <iostream>
using namespace std;
class A
{
public:
static void staticmember()
{
cout<<"static"<<endl;
} //static member
void nonstatic()
{
cout<<"nonstatic"<<endl;
} //nonstatic member
virtual void virtualmember()
{
cout<<"virtual"<<endl;
}//virtual member
};
//可以参考《C++ Primer(3rd)》第532页13.6指向类成员的指针一节~
int main()
{
A a;
//static成员函数,取得的是该函数在内存中的实际地址,而且因为static成员是全局的,所以不能用A::限定符
void(*ptrstatic)()=&A::staticmember;//以类成员的函数指针来访问类的成员函数。
//nonstatic成员函数 取得的是该函数在内存中的实际地址
void(A::*ptrnonstatic)()=&A::nonstatic;
//虚函数取得的是虚函数表中的偏移值,这样可以保证能过指针调用时同样的多态效果
void(A::*ptrvirtual)()=&A::virtualmember;
//函数指针的使用方式
ptrstatic();
(a.*ptrnonstatic)();
(a.*ptrvirtual)();
cout<<endl;
cout << "&staticmember = " << A::staticmember << endl;//地址是相当于类首地址的偏移量。
cout << "&A::virtualmember = " << &A::virtualmember << endl;
cout << "" << &ptrstatic << endl;
}
1、一个指向外部函数的指针声明为:
1、void(*str)(char*, const char*);
2、void strcpy(char* dest, const char* source);
3、str= strcpy;
2、一个指向类A成员函数的指针声明为:
1、void (A::*str)(char* , const char*);
声明解释:str是一个指向A成员函数的指针,返回无类型值,函数带有二个参数。除了在星号前增加A::,与声明外部函数指针的方法一样。
3、给成员指针赋值的方法是将函数名通过指针符号&赋予指针名。
如下所示:
class A
{
public:
void strcpy(char*, const char*);
void strcat(char*, const char*);
};
str = &A::strcpy;
2、类中的重载
2.1、构造函数的重载
2.2、普通成员函数的重载
2.3、静态成员函数的重载
代码分析:全局函数,普通成员函数以及静态成员函数之间是否可以构成重载?
#include <stdio.h>
class Test
{
private:
int i;
public:
Test()
{
printf("Test::Test()\n");
this->i = 0; //使用this初始化成员变量的值
}
Test(int i)
{
printf("Test::Test(int i)\n");
this->i = i;
}
Test(const Test& obj)
{
printf("Test::Test()const Test& obj\n");
this->i = obj.i;
}
static void func() //静态成员函数,可以直接类名访问
{
printf("Test::func()\n");
}
void func(int i)
{
printf("Test::func(int i), i = %d\n", i);
}
int getI()
{
return i;
}
};
//全局函数
void func()
{
printf("::func()\n");
}
void func(int i)
{
printf("::func(int i) , i = %d\n", i);
}
int main()
{
//全局函数func和func(1)构成重载关系,默认使用全局函数。
func(); //::func()
func(1); //::func(int i) i = 1;
printf("\n");
//构造函数之间构成重载关系
Test t; //Test::Test()
Test t1(1); //Test::Test(int i) i=1;
Test t2 = t1; //等价于 Test t2(t1); //Test ::Test(const Test& obj)
printf("\n");
//全局函数与静态成员函数不构成重载(因为作用域不同)
func(); //::func()
Test::func(); //Test::func()
printf("\n");
//全局函数与类的普通成员函数也不构成重载,作用域不同。
func(2); //::func() // i = 2;
t.func(2); //Test::func(int i) i = 2;
printf("\n");
//类中普通成员与静态成员构成重载关系(作用域相同,且符合重载条件。)
t1.func();
t1.func(3); // i =3
return 0;
}
3、重载的深度意义
3.1、通过
函数名
对
函数功能
进行提示
3.2、通过
参数列表
对
函数用法
进行提示
3.3、
扩展
系统中已经存在的函数功能。
/*************** 重载的意义分析 ************/
#include <stdio.h>
#include <string.h>
//重载strcpy函数,进行函数功能的拓展,拓展类似于 strncpy
char* strcpy(char* buf, const char* str, unsigned int n)
{
return strncpy(buf, str, n);
}
int main()
{
const char* s = "Hello World!";
char buf[20] = {0};
//strcpy(buf, s); //原来的strcpy函数,会出现缓冲区溢出。
//sizeof(s)是因为字符串的首地址(在栈上)和字符(在代码段)是分开存放的,直接测量sizeof(s)是4字节的内存。
//strcpy(buf,
s,
sizeof(s)-1);//因为字符串是\0结尾的。
//如果这里sizeof(s)-1 // buf只能打印三个字母
strcpy(buf, s, sizeof(buf)-1); //重载的函数,安全,直接测量大小,不会溢出。
printf("buf = %s\n", buf);
return 0;
}
4、小结
4.1、类的成员函数之间可以重载
4.2、重载必须发生在同一个作用域中(所以
全局函数
和
成员函数
不能构成重载关系)
4.3、重载的意义在于扩展已经存在的功能。