第29课 类中的函数重载

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、重载的意义在于扩展已经存在的功能。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值