C ++:覆盖已弃用的虚拟方法时,已弃用警告 [英] C++: Deprecation warning when overriding a deprecated virtual method

查看:102
本文介绍了C ++:覆盖已弃用的虚拟方法时,已弃用警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个纯虚拟类,该类具有一个纯虚拟方法,该方法应为 const ,但不幸的是没有。此接口在一个库中,并且该类在单独的项目中被其他几个类继承。

I have an pure virtual class that has a pure virtual method that should be const, but unfortunately is not. This interface is in a library, and the class is inherited by several other classes, in separate projects.

我正在尝试使此方法 const 而不会破坏兼容性(至少一段时间),但是当非const方法重载时,我找不到能产生警告的方法。

I'm trying to make this method const without breaking compatibility (at least for some time), but I cannot find a way to produce a warning when the non-const method is overloaded.

以下是到目前为止我能生产的产品的示例:

The following is an example of what I was able to produce so far:


  • 阶段0 :更改之前。仅存在 Interface :: doSomething()方法的非常量版本,并且它是纯虚拟的。

  • 阶段1 :在过渡期间。 Interface :: doSomething()方法的const版本和非const版本都存在。它们都具有默认实现,以允许同时使用旧样式和新样式(在此阶段,它们不能是纯虚拟的,因为每个继承的类将仅覆盖其中一个)。 const版本会调用非const版本,以确保与旧实现兼容,因此非const版本会断言,因为它永远都不会被调用。

  • 阶段2 :仅存在 Interface :: doSomething()方法的非常量版本,并且它是纯虚拟的。

  • Stage 0: Before the change. Only the non-const version of Interface::doSomething() method exists and it is pure virtual.
  • Stage 1: During the transition period. Both const and non-const versions of the Interface::doSomething() method exist. They both have a default implementation in order to allow both old style and new style implementations (they cannot be pure virtual in this stage, since each inherited class will override only one of them). The const version calls the non-const version in order to ensure compatibility with old implementations, the non-const version asserts, since it should never be called.
  • Stage 2: Only the non-const version of Interface::doSomething() method exists and it is pure virtual.

第1阶段中,我希望当类覆盖 Interface的非常量版本时能够发出警告: :doSomething(),以警告用户应该更新其代码,因此,当我切换到阶段2 时,破解他人代码的机会非常低。
不幸的是,我找不到办法。我用GCC和Clang尝试了几种标志组合。我唯一能做的就是使编译失败(例如,将其更改为 final ),但这不是我要处理的方式。有没有办法发出警告?

In Stage 1, I'd expect to be able to produce a warning when a class overrides the non-const version of Interface::doSomething(), in order to warn the user that they should update their code, so that when I switch to Stage 2 the chance to break other people's code is very low. Unfortunately I cannot find a way to do that. I tried several combinations of flags, both with GCC and Clang. The only thing I was able to do, was to make the compilation fail (e.g. changing it to final), but that's not how I want to handle this. Is there a way to produce a warning?

#include <iostream>
#include <cassert>

class Interface
{
public:
    virtual ~Interface() = default;

// callDoSomething method:
// - stage 0: non const
// - stage 1-2: const
#if (STAGE == 0)
    void callDoSomething() { doSomething(); }
#else
    void callDoSomething() const { doSomething(); }
#endif

protected:

// non-const doSomething() method:
// - stage 0: pure virtual
// - stage 1: virtual with assert in default implementation (should never be called)
// - stage 2: removed
#if (STAGE == 0)
    virtual void doSomething() = 0;
#elif (STAGE == 1)
    [[deprecated("Overload const version instead")]]
    virtual void doSomething()
    {
        assert(false);
    }
#endif

// const doSomething() method
// - stage 0: N/A
// - stage 1: virtual with default implementation (calls the non-const overload)
// - stage 2: pure virtual
#if (STAGE == 1)
    virtual void doSomething() const
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
        std::cout << "  calling non const version\n";
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
        const_cast<Interface*>(this)->doSomething();
#pragma GCC diagnostic pop
    }
#elif (STAGE == 2)
    virtual void doSomething() const = 0;
#endif
};


// Old style implementation: non-const doSomething()
// Allowed only in stages 0 and 1
#if (STAGE == 0 || STAGE == 1)
class Implementation_old : public Interface
{
public:
    virtual ~Implementation_old() = default;

protected:
    virtual void doSomething() override
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};
# endif


// Old style implementation: const doSomething()
// Allowed only in stages 1 and 2
#if (STAGE == 1 || STAGE == 2)
class Implementation_new : public Interface
{
public:
    virtual ~Implementation_new() = default;

protected:
    virtual void doSomething() const override
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};
#endif


int main(int argc, char *argv[])
{
    Interface* iface = nullptr;

#if (STAGE == 0 || STAGE == 1)
    iface = new Implementation_old;
    iface->callDoSomething();
    delete iface;
#endif

#if (STAGE == 1)
    std::cout << "-------------------\n";
#endif

#if (STAGE == 1 || STAGE == 2)
    iface = new Implementation_new;
    iface->callDoSomething();
    delete iface;
#endif

    iface = nullptr;

    return 0;
}

这是CMakeLists.txt文件,使用以下3个定义来构建示例阶段

This is the CMakeLists.txt file to build the example using the 3 definitions of STAGE

cmake_minimum_required(VERSION 3.5)
project(test_deprecate_non_const)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(main_stage_0 main.cpp)
target_compile_definitions(main_stage_0 PRIVATE STAGE=0)

add_executable(main_stage_1 main.cpp)
target_compile_definitions(main_stage_1 PRIVATE STAGE=1)

add_executable(main_stage_2 main.cpp)
target_compile_definitions(main_stage_2 PRIVATE STAGE=2)


推荐答案

使用过时的界面发出警告会很好。但是,我的尝试失败了,而您的尝试也失败了。我认为不幸的是,在设计属性时并未考虑到这一点。我认为属性适用于实体的名称,这意味着您仅在通过名称调用方法时收到警告。但是我没有研究这个标准。

It would be nice to have a warning on using a deprecated interface. However my attempts have failed as have yours. I think that unfortunately attributes were not designed with this in mind. I think an attribute applies to the name of an entity which means that you get the warning only when calling the method by name. But I did not study the standard about this.

因此,我内心充满悲伤,我会从对一个轻微相关帖子的答案

So, with sadness in my heart I will steal a conclusion from this answer to a mildly related post:


告诉您的用户,该功能已被弃用,不应继续使用。

Tell your users that the function is deprecated and shouldn't be used, then move on.

这篇关于C ++:覆盖已弃用的虚拟方法时,已弃用警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆