学习面向对象的语言,了解继承是必不可少的。您可能觉得这太基础了,大家可都是老“996”了,还用介绍封装、继承、多态那老三样吗?
😌哎,您别着急。本文讲的是一个C++语言的小Trick,您或许了解也或许不了解,各位看官请细听分说。
按常理来说,如果父类的成员函数是public的,那么子类应该也能直接调用父类定义的函数,所谓的“继承”也便是这个含义。口说无凭,手上见真章,说有这么两个类,它这样,这样,这样……
啪啪啪,你甩给我一段代码:
#include <iostream> #include <string> using namespace std; class Staff { public: void set_birth(string birth) { _birth = birth; } private: string _birth; }; class Leader:public Staff { }; int main() { Leader s; s.set_birth("1990/10/10"); return 0; }
这段代码没问题,编译也能过。父类有个成员函数set_birth,接收一个string类型,设置生日。比如"1990/10/10"。子类可以直接调用set_birth。
“这有什么值得一说的?”你夺门而出,我连忙追上去让你把门还我。
您接着瞧,如果子类现在需要实现一个传入int类型的set_birth呢?
class Leader:public Staff { public: void set_birth(int birth) { set_birth(to_string(birth)); } }; int main() { Leader s; s.set_birth(19901010); return 0; }
子类set_birth(int)内调用了父类的set_birth(string)。看着没问题,但是编译却报错了:
demo.cpp:17:19: error: no viable conversion from 'std::__1::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') to 'int' set_birth(to_string(birth)); ^~~~~~~~~~~~~~~~ /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/string:875:5: note: candidate function operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); } ^ demo.cpp:16:24: note: passing argument to parameter 'birth' here void set_birth(int birth) { ^ 1 error generated.
编译器编译子类时似乎不能识别set_birth(string)。我们再测试一下是不是真的不能识别:
class Leader:public Staff { public: void set_birth(int birth) { } }; int main() { Leader s; s.set_birth("19901010"); return 0; }
这样编译,也报错:
demo.cpp:22:17: error: cannot initialize a parameter of type 'int' with an lvalue of type 'const char [9]' s.set_birth("19901010"); ^~~~~~~~~~ demo.cpp:16:24: note: passing argument to parameter 'birth' here void set_birth(int birth) { ^ 1 error generated.
果然,子类已经无法调用父类的public成员函数了。明明刚才还可以,怎么set_birth(string)对子类突然不可见了呢?
奥秘在于,子类重载了父类的同名函数。此时父类的函数确实对子类是不可见的……
这其实不是一个复杂的知识点,只是容易让人稍不留意就遗忘。
解决方案是什么呢?其实也不难,想办法让父类的同名函数对子类可见!
class Leader:public Staff { public: using Staff::set_birth; void set_birth(int birth) { set_birth(to_string(birth)); } }; int main() { Leader s; s.set_birth(19901010); return 0; }
一行using就可以搞定!
using Staff::set_birth;
注意这不是C++11!这是C++11之前就有的using语法。