无法实现接口的 [[deprecated]] 方法

Posted

技术标签:

【中文标题】无法实现接口的 [[deprecated]] 方法【英文标题】:Cannot implement [[deprecated]] method of interface 【发布时间】:2016-08-18 16:14:21 【问题描述】:

我想将我的界面的某些方法标记为已弃用。 为了向后兼容,我需要在一段时间内支持旧方法。

// my own interface for other
interface I 
    [[deprecated( "use 'bar' instead" )]]
    virtual void foo() = 0;
;

但是Visual Studio 2015不允许我实现这个接口:

// my own implementation
class IImpl : public I 
public:
    virtual void foo() override; // here goes warning C4996:
                                 // 'I::foo': was declared deprecated
;

我使用选项Treat Wanings as Errors (/WX),所以这段代码无法编译。

我尝试在本地忽略警告:

class IImpl : public I 
public:
#pragma warning(push)
#pragma warning(disable: 4996)
    virtual void foo() override;
#pragma warning(pop)
    // ... other methods are outside
;

但它没有效果。允许编译代码的唯一解决方案是忽略整个类声明的警告:

#pragma warning(push)
#pragma warning(disable: 4996)
class IImpl : public I 
public:
    virtual void foo() override;
    // ... other methods are also affected
;
#pragma warning(pop)

GCC 似乎做对了:

#pragma GCC diagnostic error "-Wdeprecated-declarations"

interface I 
    [[deprecated]]
    virtual void foo() = 0;
;

class IImpl : public I 
public:
    virtual void foo() override; // <<----- No problem here
;

int main()

    std::shared_ptr<I> i( std::make_shared<IImpl>() );
    i->foo(); // <<---ERROR: 'virtual void I::foo()' is deprecated [-Werror=deprecated-declarations]
    return 0;

是MSVC++的bug吗? 有没有办法在 Visual Studio 中正确使用 deprecated 声明?

【问题讨论】:

声明函数[[deprecated]]然后禁用警告有什么意义? ***.com/a/295229/612920 正确的方法是禁用整个类定义的警告。由于警告实际上并没有在您的原型线上被击中...... @Kupto:私有变量可能是另一个库中已弃用的类型。这不是公共接口的一部分,但仍需要在类定义中编写。而且我会说值得警告这种弃用。 @Kupto:请确保您理解我刚刚写的内容!特别是:在哪里声明私有成员变量? 【参考方案1】:

标准说:

实现可以使用 deprecated 属性来生成诊断消息,以防万一 program 引用一个名称或实体而不是声明它

但是IImpl::foo的声明没有引用I::foo

这段话是信息丰富的,不需要完全按照。事实上,一个实现可能会警告你它想要的任何东西。我仍然认为这是一个错误。

可以这样解决:

// IInternal.h
struct I 
   virtual void foo() = 0; // no deprecation
;

// I.h
#include <IInternal.h>
[[deprecated( "use 'bar' instead" )]]
inline void I::foo()  
    std::cerr << "pure virtual function I::foo() called\n"; 
    abort(); 
 

//IImpl.h
#include <IInternal.h>
class IImpl : public I  ... // whatever

【讨论】:

以上是关于无法实现接口的 [[deprecated]] 方法的主要内容,如果未能解决你的问题,请参考以下文章

deprecated注释 原因

ImportError:无法从“sklearn.utils.validation”导入名称“_deprecate_positional_args”

xxx.java: Recompile with -Xlint:deprecation for details

深入理解java注解的实现原理

静态类无法实现接口

未调用 iOS8 接口旋转方法