C++ -- 重载、重定义、重写的区别
一.重载
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;
}