聪明的编译器

前一阵,一位朋友问我,编译器是如何知道当传入不同参数就会调用同一个类中的同名函数,我想,这也许是很多初学者经常遇到的问题,今天小豆君就来说说这个原理。

在讲原理之前,我先来讲一个生活中的例子——取名字。

好听好记的汉字就那么多,很多家长在给孩子起名字时难免“撞衫”。比如,我高中一班的一个同学叫“刘洋”,二班的同学也有个叫“刘洋”,那么我们为了区分这两个人,就可能会给她们重命名为“一班刘洋”,“二班刘洋”,这样就可以准确区分啦。

而在编程中,好用简单的英文也就是那么多个,况且我英文水平也不高,一堆程序员在一起编程,难免会起重名字。

讲到这里,我想聪明的小伙伴们就发现了,其实,在我们程序中编译器就是将所有的类名,函数名,参数类型,名字空间等等拼接起来,从而为每个函数生成了一个唯一的名字。

例如:

class MyClass
{
public:
    int fun();
    int fun(int param1);
    int fun(const int& param1);
    int fun(double param1);
    int fun(double param1, const string& param2);
    int fun() const;
};

上面的这段代码定义了5个同名参数,那么这些函数接口在编译器中的名字可能分别为

class MyClass
{
public:
    //注释为对应编译器重新生成的名字
    int fun();//=>MyClass_fun
    int fun(int param1);//=>MyClass_fun_int
    int fun(const int& param1);//=>MyClass_fun_const_int
    int fun(double param1);//=>MyClass_fun_double
    int fun(double param1, const string& param2);//=>MyClass_fun_double_string
    int fun() const;//=>MyClass_fun_const
};

当我在程序中写

MyClass c;
c.fun(25);

那么,编译器就会分析实例c是MyClass类型,只有一个参数,且25为整数类型,所以c.fun(25)被编译之后,其函数名可能变为MyClass_fun_int,那么编译器就可以根据这个唯一的名字找到我这个接口的入口地址,从而执行该入口地址所对应的代码段。

所以,你就不难理解下面的重载条件:

  • 参数个数不同,可以重载

  • 参数个数相同,但参数类型不同也可重载

  • const参数可以重载,可以把const修饰的对象和普通对象看作是两种类型

我们还知道,返回值是不能作为重载条件的,请看下面代码

比如我在MyClass类中又定义了一个返回string类型的fun接口

string fun();

那么请看下面的代码,编译器该如何翻译

MyClass c;//假设返回值可以作为重载条件
int val1 = c.fun();//重命名为 int_MyClass_fun
string val2 = c.fun();//重命名为string_MyClass_fun
c.fun();//这个该如何重命名呢?int_MyClass_fun还是string_MyClass_fun?

从上面的示例中,我们可以看出,正因为C++可以忽略接口的返回值,所以如果只用返回值来作为重载条件是不够的,也是不可取的。所以编译器会在这里报重定义的错误。

最后也希望大家多多支持小豆君的创作,关注小豆君的公众号“小豆君Qt分享”,最新文章都会在公众号第一时间发布,或者你有不懂的问题,关注公众号后,可加好友或进Qt群获得答案。

猜你喜欢

转载自blog.csdn.net/weixin_33800593/article/details/86848610