
本文共 2038 字,大约阅读时间需要 6 分钟。
关于C++中的重载、重写和重定义理解
由于 编程 语言 特性,尤其是 C++,函数的概念可能会有多个功能作用。然而,是否重载或重写这一问题往往令人困惑。本文将从基本概念出发,逐步解答重载与重写的关系与区别。
一、基本概念
重载(Overload)
重载是指在同一个类中,存在多个具有不同参数列表(参数类型、个数或顺序)相同功能名的函数。软件开发中,重载主要用于解决方法调用时的歧义性问题。需要注意的是,重载完全不关心函数的返回值类型,返回值类型变化与否均不影响是否视为重载。在编译时,根据函数的参数列表唯一确定调用哪一个函数。重写(Override)
重写则是指在派生类中重新定义基类中的函数。在派生类中,重写的函数必须与基类中的被重写函数在所有方面都一致,包括:- 功能名相同
- 参数列表完全一致
- 返回值类型一致
- 必须是虚拟函数(Virtual Function),即基类函数前面需要修饰virtual关键字
需要注意的是,派生类中执行重写时,会自动调用派生类的具体实现版本,而不是基类的。这样设计的好处是确保函数行为按照子类的特性进行。
三、重载与重写的涉及范围
区别一:所属范围
重载和被重载的函数都在同一类中;而重写和被重写的函数则分别位于相对应的父类和子类中。区别二:参数列表
重载关注的是参数列表是否不同,包括参数类型、个数或顺序的改变。而重写必须正好与基类的被重写函数参数列表一致。否则,重写是不成立的。区别三:虚拟属性
重写需要基类函数前面有一个virtual关键字,而重载则并不是这样。重载的函数可以与/或没有virtual关键字。四、重载和隐藏函数的区别
与重定义或重载不同的隐藏函数完全不遵循相同的规则。一旦函数名相同,但参数列表不同,就会发生重复定义(Overloading),这时基类主函数会被阻塞而不是被重写。需要注意,关于virtual函数的具体情况:
如果基类函数是virtual,则派生类中的如果参数列表完全相同,就可以选择隐藏主函数,而不是重写。这时,调用方法根据运行时的动态类型决定是调用哪个版本。
五、常规情况下的重载
比如类A:
class A {public: void test(int i); void test(double i); void test(int i, double j); void test(double i, int j); int test(int i); // 错误,非重载};
在这里,test(int i)
与其他测试功能不同,它并不被视为重载的原因在于返回值类型被明确声明而且参数列表无法与任何一个相同(此处可以认为该函数没能与其他test()函数相同参数列表)。需要注意的是,void test(int i, double j)
与void test(double i, int j)
是不同的重载版本,关注点在于参数的顺序不同,这也是被允许的。
至于参数顺序不同,例如:
class A {public: void test(int a, int b); void test(int b, int a); // 这不是重载};
这种情况就不能算作重载。因为仅仅参数顺序不同,而参数的类型不同,所以我们在编译时会遇到错误:
#includeusing namespace std;class A {public: void test(int a, int b) { cout << a + b << endl; cout << "test(int a, int b)" << endl; } void test(int b, int a) { cout << a + b << endl; cout << "test(int b, int a)" << endl; }};int main() { cout << "hello world" << endl; return 0;}
编译时会出错,提示无法重载,因为你提供的void A::test(int, int)
和void test(int b, int a)
在参数类型上是一样的,只是顺序不同。在编译过程中,会被视为一个简单的函数定义,故引发无法重载的错误。
总结关键点:能否被视作重载取决于是否存在唯一的函数调用方式,避免出现语义悬殊的情况。如果函数参数由不同顺序组成但参数类型相同,那仍然是被视为有重复函数定义,这会导致无法重载。
结论是,只有当参数类型、个数或顺序有差异时,才能被视为重载。如果只是顺序不同而参数类型相同,还是重复定义,导致无法通过编译。因此,在编写代码时,当仅仅是参数顺序不同还需要参数类型相同时,即使这样,也不利于代码的可读性。所以,最好还是避免这样写代码。
发表评论
最新留言
关于作者
