【问题标题】:Explicitly hide a base function in C++在 C++ 中显式隐藏基函数
【发布时间】:2014-04-06 14:02:23
【问题描述】:

C++11 引入了非常有用的说明符 override 用于显式覆盖一个基本虚函数。但是显式隐藏呢?

例如,考虑代码:

struct A: B {
    void f();
}
  1. 如果存在虚拟void B::f(),代码会导致隐式覆盖此函数。
  2. 如果存在非虚拟的void B::f(),代码会导致隐藏此功能。

即代码的含义取决于void B::f()的存在性和虚拟性。

问题。如何显式隐藏基函数?如果我尝试隐藏虚拟功能,我想得到错误。

override守卫,以保证虚基函数具有相同的原型,我需要一个守卫来确保没有具有相同原型的虚拟基函数。


史诗般的失败示例:

#include <stdio.h>

struct B {
    void f() {printf("Hello\n");}
    void g() {f();}
};

struct A: B {
    void f() {g();}
};

int main() {
    A a;
    a.f();
    return 0;
}

程序打印“你好”。但是如果我将B::f() 设为虚拟程序会导致分段错误(无限递归)。如果B 类是第三方的并且我只是#include 它,这可能是一个真正的问题,那就是更改第三方代码中的虚拟性可能会导致我的代码出现错误。

UPD。我通过 new 说明符找到了 C# have this feature。似乎 C++ 还没有(还没有?)。

【问题讨论】:

  • 因为如果B::f() 是虚拟的并且A::f 覆盖它,那么A::f 调用g::f,它调用A::f,它调用g::f,它调用A::f.. 也就是无限递归。 . 它不调用B::f
  • 您可能符合条件:void g() { B::f(); }
  • @DieterLücking:我已经更新了我的帖子。基类的代码并不总是可以控制的。
  • @Corvus 那么,你必须打破这个圈子——意思是——你不能打电话给B::g()
  • @DieterLücking: B::g() 是任意基函数。我什至不知道它叫f()。你建议我根本不要调用基本函数吗?..

标签: c++


【解决方案1】:

你可以用什么来检查基类:

// Class to check that B::f() is not virtual
// struct A requires that this class compiles, else struct A should epic fails.
struct checkInterfaceIsNotVirtual_B : B
{
    void f() = delete;
};

如果B::f() 是虚拟的,它将无法编译:

  • g++:

    error: deleted function 'virtual void checkInterfaceIsNotVirtual_B::f()'
    
  • 叮当++:

    error: deleted function 'f' cannot override a non-deleted function
    

【讨论】:

  • 请注意,只有f() 的签名与基本函数完全匹配时才有效。如果基本函数是(例如)void B::f() constcheckInterfaceIsNotVintual_B 最终会隐藏 f() 而不会覆盖它。
【解决方案2】:

C++11标准的§8.4.1.1定义了函数/方法定义形式:

8.4 函数定义

8.4.1 一般情况

1 函数定义的格式为

  函数定义
attribute-specifier-seqopt decl-specifier-seqopt 声明符 virt-specifier-seqopt 函数体
函数体
ctor-initializeropt 复合语句
功能尝试块
= default ;
= delete ;

virt-specifier 在 §9.2 中定义为:

virt-specifier:
override
final

所以,不,没有类似于override 的关键字用于隐藏。

【讨论】:

  • 但是可能有 GCC 扩展吗?还是计划在标准的未来版本中引入此功能?
  • 我想不出来。也许-Wshadow 可以在它发生时警告你,但我的机器上没有 GCC 来验证它警告你这种情况,它会警告你很多其他的事情你可能不想要。
猜你喜欢
  • 2020-08-24
  • 1970-01-01
  • 2013-02-25
  • 2011-01-30
  • 1970-01-01
  • 2011-10-07
  • 2011-05-23
  • 2023-03-22
  • 2013-07-12
相关资源
最近更新 更多