几天前,我们发布了 两个C++测验 基于论坛上发布的问题。让我们复习第一个问题
- #包括
- 班 福{
- 公众的 :
- 事实上的 无效 DoStuff()=0;
- };
- 班 酒吧: 公众的 福{
- 公众的 :
- 事实上的 无效 多斯凝灰岩( 内景 a) =0;
- };
- 班 巴兹: 公众的 酒吧{
- 公众的 :
- 无效 多斯凝灰岩( 内景 (一) 覆盖
- {
- 标准::cout<< “Baz::DoStuff(int)” ;
- }
- 无效 多斯塔夫() 覆盖
- {
- 标准::cout<< “Baz::DoStuff()” ;
- }
- };
- 内景 主(){
- 巴兹巴兹;
- 巴*巴=&baz;
- pBar->DoStuff();
- }
这家伙很沮丧,因为他期待两件事:
- 代码编译时不会出错。
- 30号线最后会打电话来 Baz::DoStuff() 反过来,它会在输出控制台中打印相同的内容。
相反,他在同一行中得到了以下编译时错误
e:foo.cpp(30):错误C2660:’Bar::DoStuff’:函数不接受0个参数
这个编译错误的根源在第11行:因为我们正在关闭类的定义 酒吧 不提方法 多斯凝灰岩 没有论据,但是 多斯凝灰岩 在第10行中,有一个接受类型为的参数的版本 内景 ,我们只是把原稿藏起来 Foo::Stuff() 宣言。话虽如此,编译错误还是有道理的。
事实上 Foo::Stuff() 一个纯虚拟的方法根本不是发生这种情况的必要条件。虚拟方法和非虚拟方法也会发生这种情况。 |
我感觉到java和C语言开发人员在编码C++中的伪像时可能会遇到这种情况,因为在这些语言中,隐藏声明的概念是不可用的(有一种替代方法,包括声明成员为 私有的 ,因此子类不会使它们可见,但在这种情况下,隐藏内容的决定权属于超类的编码者。在C++中,决策是由派生类的编码器来进行的。
我的朋友如何克服这个错误以使应用程序按他所期望的那样工作?通过在Bar的定义中包含using声明,如第5行的声明:
- 班 酒吧: 公众的 福{
- 公众的 :
- //使用从基中引入名称
- //在派生类作用域中初始化。
- 使用 Foo::DoStuff;
- 事实上的 无效 多斯凝灰岩( 内景 a) =0;
- };
现在应用程序按最初的预期运行。
在测验2中,我们刚刚回顾的C++原理也适用,但是如果隐藏不是我们想要做的,这个问题可能变成更危险的事情,因为应用程序无论如何都会编译,而在运行时必须发现不希望的行为。
- #包括
- 班 福{
- 公众的 :
- 事实上的 无效 多斯凝灰岩( 烧焦 a) =0;
- };
- 班 酒吧: 公众的 福{
- 公众的 :
- 事实上的 无效 多斯凝灰岩( 内景 a) =0;
- };
- 班 巴兹: 公众的 酒吧{
- 公众的 :
- 无效 多斯凝灰岩( 内景 (一) 覆盖
- {
- 标准::cout<< “Baz::DoStuff(int)” ;
- }
- 无效 多斯凝灰岩( 烧焦 (一) 覆盖
- {
- 标准::cout<< “Baz::DoStuff(字符)” ;
- }
- };
- 内景 主(){
- 巴兹巴兹;
- 巴*巴=&baz;
- pBar->DoStuff公司( “a” );
- }
尽管事实上 Foo::DoStuff(字符) 在第30行中不可见,作为参数接收的’a’隐式转换为 内景 类型,生产:
同样,这里的解决方案是基于前面的using声明:
- 班 酒吧: 公众的 福{
- 公众的 :
- 使用 Foo::DoStuff;
- 事实上的 无效 多斯凝灰岩( 内景 a) =0;
- };
一旦声明,我们只需编译,运行和…瞧à
总之,隐藏基类方法既不是坏事,也不是要避免的事情,只要它正是您想要得到的。