在重载
父类的同名虚函数时会出现hides overloaded virtual function
编译警告。
从字面上的意思其实就可以理解:重载的虚函数被隐藏了。
三个关键点:
- 重载
- 虚函数
- 隐藏
这个编译警告之所以出现,是因为上面三个关键点,首先是发生了重载
,子类重载了父类的函数,其次被重载的是虚函数,这时这个被重载的父类的虚函数将会被隐藏。
何为隐藏呢,应该是不能使用子类实例直接调用父类被隐藏的函数,调用时必须指定父类命名空间,往深了说也就是编译器如果在子类中发现了要使用的函数的名字,注意,是名字不包含函数签名,只要名字匹配上,就不会再去父类中去寻找这个名字的函数,即便子类中的函数参数不匹配,也不会再去父类中寻找。
其实去掉虚函数
这个关键点,在c++中当重载了父类的函数时,隐藏同样会发生,举个例子:
1 | class A { |
当重载的父类函数为虚函数时,代码如下:
1 | class A { |
编译错误依旧,但多了一个编译警告,关于这个编译警告,有种解释说是为了避免书写错误,这就要说到多态,上面的例子没有应用多态有些不合适,修改一下:
1 | class BookA; //改动处 |
与之前的例子的区别是多声明了两个类:BookA
和BookB
,函数的参数类型换成了这两个类,最重要的一点是main
函数中将实例B声明为了A类型,此时就可以比较清晰的看出为什么这个警告是为了书写错误:
假设我们就是要在B类中重写父类A的void foo(BookA *)
函数,以便在main
函数中实现以类型A的实例去调用B对象的重写函数(多态调用),但却因为书写错误,把B类行的函数的参数写成了BookB *
,这就与初衷不符了,此时这个编译警告就是有价值的了。
再假设,我们就是要在B类中声明void foo(BookB *)
这么一个函数,且并不是为了重写父类中的函数,那么此时这个编译警告就是多余的,我们可以使用using
来避免这个警告,例如在类B中做出如下声明:
1 | class B : public A{ |
这样就是告诉编译器,我们明确要使用这两个函数,并不是为了重写,这样有一个可能不期望出现的情况,就是B的实例也可调用void foo(BookA *)
函数,如果不想这个情况发生,可以把using
放到私有的里面,这样既解决了编译警告,又不会暴露父类的这个函数出去:
1 | class B : public A{ |
参考了一个帖子:
https://stackoverflow.com/questions/18515183/c-overloaded-virtual-function-warning-by-clang