一.重载
1.在同一个作用域下,函数名相同,函数的参数不同(参数不同指参数的类型或参数的个数不相同)
2.不能根据返回值判断两个函数是否构成重载。
3.当函数构成重载后,调用该函数时,编译器会根据函数的参数选择合适的函数进行调用。
4.构成重载的例子:
#include
<iostream>
using
namespace
std;
int
Add(
int
a
,
int
b
)
{
return
a
+
b
;
}
double
Add(
double
a
,
double
b
)
{
return
a
+
b
;
}
int
main()
{
cout << Add(3, 4) << endl;
cout << Add(3.1, 4.1) << endl;
system(
"pause"
);
return
0;
}
5.运行结果:
二.重定义(隐藏)
1.在不同的作用域下(这里不同的作用域指一个在子类,一个在父类 ),函数名相同的两个函数构成重定义。
2.当两个函数构成重定义时,父类的同名函数会被隐藏,当用子类的对象调用同名的函数时,如果不指定类作用符,就只会调用子类的同名函数。
3.如果想要调用父类的同名函数,就必须指定父类的域作用符。
注意:当父类和子类的成员变量名相同时,也会构成隐藏。
4.隐藏的例子:
(1)定义一个B的对象b,当访问同名的函数fun1时,不指定域,会默认访问子类的fun1。
(2)
定义一个B的对象b,当访问同名的函数fun1时,指定域为A,则会访问父类的fun1。
(3)将父类与子类的同名函数fun1进行如下改写,使这两个函数的参数不同,
class
A
{
public
:
void
fun1(
char
c
)
{
cout <<
"A::fun1()"
<< endl;
}
int
_a;
};
class
B
:
public
A
{
public
:
void
fun1(
int
a
,
int
b
)
{
cout <<
"B::fun1()"
<< endl;
}
int
_b;
};
int
main()
{
B
b;
b.fun1(
'a'
);
system(
"pause"
);
return
0;
}
当定义B的对象b,调用与父类参数相同的同名函数时会出现错误,因为子类隐藏了父类的同名成员函数,不指定域,只会调用子类的同名成员函数,而传的参数与子类同名成员函数的参数不同,所以会编译失败
三.重写(覆盖)
1.在不同的作用域下(一个在父类,一个在子类),函数的函数名、参数、返回值完全相同,父类必须含有virtual关键字(协变除外)。
2.什么是协变?
(1)函数的函数名相同,参数也相同,但是函数的返回值可以不同(但必须只能是一个返回父类的指针(或引用)一个返回子类的指针(或引用),父类必须含有virtual关键字。
(2)构成协变的一种方式,返回指针;
class
A
{
public
:
virtual
A
* func1()
{
cout <<
"A::func1()"
<< endl;
return
this
;
}
private
:
int
_a;
};
class
B
:
public
A
{
public
:
virtual
A
* func1()
{
cout <<
"B::func1()"
<< endl;
return
this
;
}
private
:
int
_b;
};
int
main()
{
A
a;
B
b;
A
* p = &a; //多态的场景
p->func1();
p = &b;
p->func1();
system(
"pause"
);
return
0;
}
则运行结果如下:(因为是父类对象的指针,由包含协变,所以构成多态,指向父类调父类指向子类调子类)
(3)构成协变的另一种方式,返回引用;
class
A
{
public
:
virtual
A
& func1()
{
cout <<
"A::func1()"
<< endl;
return
*
this
;
}
private
:
int
_a;
};
class
B
:
public
A
{
public
:
virtual
A
& func1()
{
cout <<
"B::func1()"
<< endl;
return
*
this
;
}
private
:
int
_b;
};
int
main()
{
A
a;
B
b;
A
* p = &a;
p->func1();
p = &b;
p->func1();
system(
"pause"
);
return
0;
}
运行结果如下,仍然构成多态
3.构成重写的代码:
class
A
{
public
:
virtual
void
func1()
{
cout <<
"A::func1()"
<< endl;
}
private
:
int
_a;
};
class
B
:
public
A
{
public
:
virtual
void
func1()
{
cout <<
"B::func1()"
<< endl;
}
private
:
int
_b;
};
int
main()
{
A
a;
B
b;
A
* p = &a;
p->func1();
p = &b;
p->func1();
system(
"pause"
);
return
0;
}