【问题标题】:Purposely hidden overloaded function warning avoidance故意隐藏重载函数警告避免
【发布时间】:2017-02-07 21:18:37
【问题描述】:

考虑以下 C++ 示例 main.cpp 文件:

class FooIf
{
public:
    virtual int handle(char *req, char *res) = 0;
};

class BarIf
{
public:

    virtual void handle(char *msg) = 0;
};

class Bar : private BarIf
{
private:
    void handle(char * msg){}
};

class Zoo : public FooIf, public Bar
{
public:
    using FooIf::handle;
public:
    int handle(char *req, char *res){ return (0); }
};

int main(){

    Zoo zoo;
    return (0);
}

我收到了这个警告:

$ clang++ -ggdb -c main.cpp -Wall
main.cpp:23:6: warning: 'Zoo::handle' hides overloaded virtual function [-Woverloaded-virtual]
        int handle(char *req, char *res){ return (0); }
            ^
main.cpp:17:7: note: hidden overloaded virtual function 'Bar::handle' declared here: different number of parameters (1 vs 2)
        void handle(char * msg){}
             ^

现在 .. 我确实在隐藏 Bar::handle,而且我正在这样做故意

有没有办法在解决这个问题时避免抑制警告?

不用说g++ 一点也不抱怨。

【问题讨论】:

  • 你不应该故意这样做。您正在破坏多态性的意图。如果您不想要多态性,请使用封装。
  • 我不明白你的意思,你能举个例子吗?我在这里找到的唯一答案是(stackoverflow.com/questions/18515183/…),而且对我来说绝对更像是一个借口,而不是真正的动机。我很乐意避免删除警告,但不想仅仅因为 clang 想防止我输入错误就搞砸代码..
  • 句柄的定义放错了地方。多态基类要求所有派生类实现基类中的所有方法。所以从 BarIf 中删除 handle(),因为你不需要它——或者从其他东西派生 Zoo
  • TL;DR:警告应该是一个错误。类的设计被破坏了。
  • > 不用说 g++ 对此一点也不抱怨。嗯?

标签: c++ clang warnings overloading hidden


【解决方案1】:

警告标识可能的问题。

可能是这里的关键词。如果您忽略警告,您的代码可以完全正常运行。但在数以百万计的开发人员超过数万亿行代码的经验中,编译器会说“这是个坏主意”。

修复它包括取消警告,或者只是重命名方法。

这是一个潜在的警告,因为 handle 在该类中的含义会根据您调用它的方式而有很大的不同。此外,人们有时会意外未能通过给函数赋予稍微不同的签名来重载函数。

在两者之间,值得将其标记为警告。

修复它的最佳途径将取决于您的问题中未显示的详细信息。

【讨论】:

  • 是的,我想了解的是警告的动机......在我的情况下似乎相当简单:不要以相同的方式调用两个函数,即使它们有如果它们彼此不相关,则使用不同的指纹,因为这会使人们感到困惑..
【解决方案2】:

您应该考虑不同的设计。如果您真的需要,这似乎是代码异味/设计问题。

如果(无论出于何种原因)您确实想要这样做,您可以在特定位置关闭警告。请参阅此处了解信息http://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas

在你的情况下,这看起来像这样

class Zoo : public FooIf, public Bar
{
public:
    using FooIf::handle;
public:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
    int handle(char *req, char *res){ return (0); }
#pragma clang diagnostic pop
};

【讨论】:

  • 真的很感激,但我错过了关于错误设计的要点。如果我给handle 方法之一起一个不同的名称,那就很好了。这里的设计是一个从虚拟纯接口和另一个类继承的类,它不小心有一个名称冲突的方法。这个设计有什么问题?
  • @RiccardoManfrin 为什么首先需要隐藏它?为什么不将函数重命名为适当的名称? “句柄”是一个非常通用的名称。如果没有细节,我不能真正告诉你这个设计的问题在哪里。正如我所说,这是一种代码气味。有些东西闻起来有问题,这通常表明您的设计存在问题。如果有人看到它是从 BarIf 派生的并调用句柄并期望调用“BarIf::handle”,这可能会导致意外行为。而且编译器不会捕捉到这一点,所以你会遇到潜在的运行时错误。
  • 您对此(重命名)是对的,我即将以这种方式解决。然而,如果重命名是解决方案,那么设计不一定是错误的。设计细节:Zoo 等价于 Bar 并且必须公开完全相同的 API,加上一些额外的方法来专门化它:它是 Bar 的一个特化,扩展了它的属性但必须公开相同的 API(我不想重写)。同时,Zoo 必须响应 ZooIf 定义的另一个(完全不同的)API,该 API 由完全不同的组件处理。
  • @RiccardoManfrin 我是“糟糕的设计”,更多的是指“故意隐藏”,如果由于某种原因你必须这样做(并且重命名不是一个选项),这似乎有某处有问题。不过,可能有非常具体的原因需要这个(例如 3rd 方库)。如果隐藏是“偶然的”,因为两个接口在函数中具有相同的名称,而不是简单地重命名。
  • 一路意外(感觉好多了)。
猜你喜欢
  • 2011-09-18
  • 2015-10-05
  • 1970-01-01
  • 2019-07-09
  • 2019-04-16
  • 1970-01-01
  • 2017-08-12
  • 2011-04-09
  • 2016-12-25
相关资源
最近更新 更多