从几个例子看函数重载

更新时间:2023-11-06 01:05:48 阅读: 评论:0


2023年11月6日发(作者:梅铨)

从⼏个例⼦看函数重载

常⽤的⼏类函数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

#include

void func(int a){

std::cout << "global func: " << a << std::endl;

}

namespace test{

void func(int a){

std::cout << "namespace test func: " << a << std::endl;

}

};

class Demo {

public:

void func(int a){

i = 1;

std::cout << "class member func: " << a << std::endl;

}

int i{0};

};

int main()

{

func(1);

test::func(1);

Demo d;

d.func(1);

return 0;

}

函数的重载

对于程序的整个⽣命周期如下:编写程序(源代码)-> 预处理 -> 编译(扫描->词法分析->语法分析->语义分析->源代码优化->代码⽣成->⽬

标代码优化) -> 汇编 -> 链接 -> 运⾏;

编译器将源代码编译产⽣⽬标⽂件时,符号名与相应的变量和函数进⾏对应,在⽐较早的时候,两者是⼀样的,⽐如汇编源代码中包含⼀个

函数foo,编译成⽬标⽂件时,对应的符号名也是foo;C语⾔的规则⽐较类似,将全局变量和函数的符号名前加上下划线"_";

⽐如:

1

2

3

4

5

extern "C" {

void func(int a){

std::cout << "global func: " << a << std::endl;

}

}

编译成的符号如下(readelf -s main | grep func):

Num: Value Size Type Bind Vis Ndx Name

60: 11e9 74 FUNC GLOBAL DEFAULT 16 func

由于C语⾔的符号⽣成规则如此,所以不⽀持函数的重载。也因此只要符号相同(相同的函数名、变量名会编译失败)

那么对于C++,它拥有类、继承、虚机制、重载、名称空间等这些特性,使符号管理(符号⽣成规则)更为复杂。为了⽀持这些特性,发明了

Name Decoration 或 Name Mangling机制

看如下函数的符号是如何:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

int func(int){return 0;};

float func(float){return 0;};

class C{

public:

int func(int){return 0;};

class C2 {

public:

int func(int){return 0;};

};

};

namespace N{

int func(int){return 0;};

class C{

public:

int func(int){return 0;};

};

};

int main(){

func(1);

func(1.0f);

C c;

c.func(1);

C::C2 c2;

c2.func(1);

N::func(1);

N::C c1;

c1.func(1);

return 0;

}

命令:

编译: g++ -o main

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

<type> ::= <builtin-type>

::= <qualified-type>

::= <function-type>

::= <class-enum-type>

::= <array-type>

::= <pointer-to-member-type>

::= <template-param>

::= <template-template-param> <template-args>

::= <decltype>

::= P <type> # pointer

::= R <type> # l-value reference

::= O <type> # r-value reference (C++11)

::= C <type> # complex pair (C99)

::= G <type> # imaginary (C99)

::= <substitution> # See Compression below

<CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const

<builtin-type> ::= v # void

::= w # wchar_t

::= b # bool

::= c # char

::= a # signed char

::= h # unsigned char

::= s # short

::= t # unsigned short

::= i # int

::= j # unsigned int

::= l # long

::= m # unsigned long

::= x # long long, __int64

::= y # unsigned long long, __int64

::= n # __int128

::= o # unsigned __int128

::= f # float

::= d # double

::= e # long double, __float80

::= g # __float128

::= z # ellipsis

::= Dd # IEEE 754r decimal floating point (64 bits)

::= De # IEEE 754r decimal floating point (128 bits)

::= Df # IEEE 754r decimal floating point (32 bits)

::= Dh # IEEE 754r half-precision floating point (16 bits)

::= DF <number> _ # ISO/IEC TS 18661 binary floating point type _FloatN (N bits)

::= DB <number> _ # C23 signed _BitInt(N)

::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)

::= DU <number> _ # C23 unsigned _BitInt(N)

::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)

::= Di # char32_t

::= Ds # char16_t

::= Du # char8_t

::= Da # auto

::= Dc # decltype(auto)

::= Dn # std::nullptr_t (i.e., decltype(nullptr))

::= u <source-name> [<template-args>] # vendor extended type

函数的名称修饰是否包含返回值,有:

Whether the mangling of a function type includes the return type depends on the context and the nature of the function.

The rules for deciding whether the return type is included are:

1. Template functions (names or types) have return types encoded, with the exceptions listed below.

2. Function types not appearing as part of a function name mangling, e.g. parameters, pointer types, etc., have return

type encoded, with the exceptions listed below.

3. Non-template function names do not have return types encoded.

The exceptions mentioned in (1) and (2) above, for which the return type is never included, are

1. Constructors.

2. Destructors.

3. Conversion operator functions, e.g. operator int.

const重载

先看下⾯⼏个例⼦:

1:

1

2

3

4

5

6

和2:

1

2

3

4

5

6

void func(int& a){

std::cout << "global func: " << a << std::endl;

}

void func(const int& a){

std::cout << "global func: " << a << std::endl;

}

void func(int a){

std::cout << "global func: " << a << std::endl;

}

void func(const int a){

std::cout << "global func: " << a << std::endl;

}

先猜测下上述两个例⼦表现如何?

结论:例1编译失败(error: redefinition of ‘void func1(int)’ 相同的函数符号相同),例2编译成功;为什么呢?

从编译出的符号进⾏倒推:

函数原型符号

void func(int)_Z4funci

1

2

3

4

5

6

7

8

9

10

11

12

编译ok;

class Demo {

public:

void func(int a){

i = 1;

std::cout << "class member func: " << a << std::endl;

}

void func(int a) const {

// i = 1; // compile fail

std::cout << "class member const func: " << a << std::endl;

}

int i{0};

};

函数原型符号

void const Demo::func(int)_ZNK4Demo4funcEi

void Demo::func(int)_ZN4Demo4funcEi

第⼆个成员函数的const是修饰Demo object的。

const修饰返回值时,由于“Non-template function names do not have return types encoded”;对于这种情况,返回值使⽤和不

使⽤const修饰⽣成的符号是相同的,若同时存在则会编译失败。


本文发布于:2023-11-06 01:05:48,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1157866.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:符号名字
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图