在C++中同名函数有三种关系:
- 重载(overlode):相同作用域;函数名相同;参数列表不同(参数类型不同,或者参数个数不同,或者参数个数和参数类型都不相同);返回类型随意。
- 覆盖(override):不同作用域下(分别在父类和子类中);函数名相同;参数列表列表相同;返回类型相同(协变除外);基类函数必须有virtual修饰;父类和子类的访问限定可以不同。
- 隐藏(overhide):不同作用域下(分别在父类和子类中);函数名相同;除过覆盖的同名函数都是隐藏关系。
一:重载
产生原因:主要是因为在C++中,编译器在编译.cpp文件中当前作用域的同名函数时,函数生成的符号由返回值类型(不起决定作用)+形参类型和顺序(起决定作用)的组成。
作用:用同一个函数名命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。
复制代码
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
30int sum(int a,int b) { return a+b; } double sum(double a,double b) { return a+b; } float sum(float a,float b) { return a+b; } int main() { /* 调用函数名相同的函数, 根据实参的类型和实参的顺序以及实参的个数选择相应的函数 */ int a=sum(10,20);//调用的是int sum(int a,int b) //call sum (010B1447h) ==》 静态的绑定 float b=sum(2.5f,3.2f);//调用的是float sum(float a,float b); //call sum (010B145Bh) ==》 动态的绑定 cout<<a<<endl; cout<<b<<endl; return 0; }
同样的如下也构成重载
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14void add(int* a)//参数类型不同 { cout<<*a<<endl; } void add(int& a) { cout<<a<<endl; } int main() { int a=10; add(&a); add(a); }
二、覆盖
在子类中定义了一个与父类完全相同的函数时,称子类这个函数覆盖了父类的这个虚函数。完全相同代表着两个函数的函数名、参数个数、参数类型、返回值类型都相同;也有特殊例子(协变)。
覆盖的作用:实现动态的多态。
第一种情况:
复制代码
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//情况一:普通情况 class Base { public: virtual void Show() { cout<<"Base::Show()"<<endl; } protected: int ma; }; class Derive:public Base { public: /*在子类中定义了一个和父类虚函数完全相同的函数; 如果不显示加上virtulal修饰,编译器会默认为虚函数。 */ void Show() { cout<<"Derive::Show()"<<endl; } protected: int mb; }; void Fun(Base* p) { p->Show(); } void Fun(Base& p) { p.Show(); } int main() { Base p; Derive d; Fun(p); Fun(&p); /* 打印的是Derive::Show() 父类的引用引用了基类的对象,调用覆盖函数时调用的是基类的虚函数 */ Fun(d); /* 打印的是Derive::Show() 父类的指针指向了基类的对象,调用覆盖函数时调用的是基类的虚函数 */ Fun(&d);//打印的是Derive::Show() return 0; }
第二种情况:
协变:子类的虚函数和父类中的虚函数的函数名、参数个数、参数类型都相同,只是返回值类型不同,父类的虚函数返回的时父类的指针或者引用,子类的虚函数返回的时子类的指针或者引用,这种情况下也会产生子类的虚函数覆盖父类的虚函数。
复制代码
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//情况二:协变覆盖 class Base { public: virtual Base& Show()//基类的虚函数返回基类的引用 { cout<<"Base::Show()"<<endl; return *this; } protected: int ma; }; class Derive:public Base { public: Base& Show()//子类的虚函数,返回子类的引用 { cout<<"Derive::Show()"<<endl; return * this; } protected: int mb; }; void Fun(Base* p) { p->Show(); } void Fun(Base& p) { p.Show(); } int main() { Base p; Derive d; Fun(p); Fun(&p); Fun(d);//call eax Fun(&d); return 0; }
三、隐藏:
隐藏的不光是成员函数,还可以是成员变量。
★在子类的内部或者外部(通过子类成员)访问该成员,全部访问的子类同名成员。
★在子类的内部或者外部(通过子类成员)访问该同名的成员函数,调用的是子类的成员函数。
复制代码
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69class A { public: A(int x=10):ma(x),mb(x){} //举例1 //void Show() //{ // cout<<"A::Show()"<<endl; //} //举例2 //virtual void Show() //{ // cout<<"A::Show()"<<endl; //} //举例2 void Show(int a) { cout<<"A::Show(int)"<<endl; } public: int ma; int mb; }; class B:public A { public: B(int x=20):ma(x){} //举例1 //void Show() //{ // cout<<"B::Show()"<<endl; // cout<<ma<<endl;//在子类中访问同名的成员,访问的是子类中的 //} //举例2 //void Show(int a) //{ // cout<<"B::Show()"<<endl; // cout<<ma<<endl; //} //举例3 void Show(int a,int b) { cout<<"B::Show()"<<endl; cout<<ma<<endl; } public: int ma; }; /* A:: B:: ma mb ma */ int main() { B b; cout<<(b.ma)<<endl; cout<<(b.mb)<<endl; //b.show(1); b.Show(1,2); return 0; }
最后
以上就是呆萌香水最近收集整理的关于C++中同名函数之间的关系的全部内容,更多相关C++中同名函数之间内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复