前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >C++ Trick:小心,子类隐藏父类成员函数

C++ Trick:小心,子类隐藏父类成员函数

作者头像
果冻虾仁
发布2021-12-08 13:45:28
发布2021-12-08 13:45:28
1.8K00
代码可运行
举报
文章被收录于专栏:后台公论后台公论
运行总次数:0
代码可运行

学习面向对象的语言,了解继承是必不可少的。您可能觉得这太基础了,大家可都是老“996”了,还用介绍封装、继承、多态那老三样吗?

哎,您别着急。本文讲的是一个C++语言的小Trick,您或许了解也或许不了解,各位看官请细听分说。

按常理来说,如果父类的成员函数是public的,那么子类应该也能直接调用父类定义的函数,所谓的“继承”也便是这个含义。口说无凭,手上见真章,说有这么两个类,它这样,这样,这样……

啪啪啪,你甩给我一段代码:

代码语言:javascript
代码运行次数:0
复制
#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呢?

代码语言:javascript
代码运行次数:0
复制
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)。看着没问题,但是编译却报错了:

代码语言:javascript
代码运行次数:0
复制
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)。我们再测试一下是不是真的不能识别:

代码语言:javascript
代码运行次数:0
复制
class Leader:public Staff {
public:
    void set_birth(int birth) {
    }
};

int main() {
    Leader s;
    s.set_birth("19901010");
    return 0;
}

这样编译,也报错:

代码语言:javascript
代码运行次数: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)对子类突然不可见了呢?

奥秘在于,子类重载了父类的同名函数。此时父类的函数确实对子类是不可见的……

这其实不是一个复杂的知识点,只是容易让人稍不留意就遗忘。

解决方案是什么呢?其实也不难,想办法让父类的同名函数对子类可见!

代码语言:javascript
代码运行次数:0
复制
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语法。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程往事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档