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

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

学习面向对象的语言,了解继承是必不可少的。您可能觉得这太基础了,大家可都是老“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语法。

相关文章
|
2月前
|
设计模式 算法 安全
【C/C++ 关键字 函数说明符 】C++ final关键字(修饰成员函数无法被子类重写覆盖)
【C/C++ 关键字 函数说明符 】C++ final关键字(修饰成员函数无法被子类重写覆盖)
42 1
|
9天前
|
安全 编译器 C++
【C++类和对象】const成员函数及流插入提取
【C++类和对象】const成员函数及流插入提取
|
21天前
|
存储 编译器 C++
C++:类之六脉神剑——默认成员函数
C++:类之六脉神剑——默认成员函数
31 0
|
22天前
|
存储 编译器 C++
【C++成长记】C++入门 | 类和对象(中) |拷贝构造函数、赋值运算符重载、const成员函数、 取地址及const取地址操作符重载
【C++成长记】C++入门 | 类和对象(中) |拷贝构造函数、赋值运算符重载、const成员函数、 取地址及const取地址操作符重载
|
22天前
|
编译器 C++
【C++成长记】C++入门 | 类和对象(中) |类的6个默认成员函数、构造函数、析构函数
【C++成长记】C++入门 | 类和对象(中) |类的6个默认成员函数、构造函数、析构函数
|
22天前
|
存储 编译器 C++
【C++成长记】C++入门 | 类和对象(上) |类的作用域、类的实例化、类的对象大小的计算、类成员函数的this指针
【C++成长记】C++入门 | 类和对象(上) |类的作用域、类的实例化、类的对象大小的计算、类成员函数的this指针
|
2月前
|
编译器 C语言 C++
【C++练级之路】【Lv.3】类和对象(中)(没掌握类的6个默认成员函数,那你根本就没学过C++!)
【C++练级之路】【Lv.3】类和对象(中)(没掌握类的6个默认成员函数,那你根本就没学过C++!)
|
2月前
|
设计模式 安全 C++
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
241 2
|
2月前
|
存储 编译器 程序员
【C/C++ 基础知识 】深入C++:特殊成员函数的底层原理与规则
【C/C++ 基础知识 】深入C++:特殊成员函数的底层原理与规则
59 0
|
2月前
|
算法 Serverless 数据安全/隐私保护
【C++ 函数 基本教程 第三篇 】深度解析C++函数类型:探寻全局函数、成员函数与静态函数的奥秘
【C++ 函数 基本教程 第三篇 】深度解析C++函数类型:探寻全局函数、成员函数与静态函数的奥秘
45 1