C++11 C++;使用名称空间进行版本控制可能会导致重写的继承问题

C++11 C++;使用名称空间进行版本控制可能会导致重写的继承问题,c++11,namespaces,overriding,api-design,binary-compatibility,C++11,Namespaces,Overriding,Api Design,Binary Compatibility,我们正在尝试使用名称空间为API的版本命名,尽管我们认为虚拟函数会出现一些问题: namespace v1 { class someParam { public: someParam() {}; virtual ~someParam() {}; }; class someClass { public: someClass() {}; virtual ~someClass() {};

我们正在尝试使用名称空间为API的版本命名,尽管我们认为虚拟函数会出现一些问题:

namespace v1 {
    class someParam {
    public:
        someParam() {};
        virtual ~someParam() {};
    };

    class someClass {
    public:
        someClass() {};
        virtual ~someClass() {};
        virtual bool doSomething(someParam a);
    };


    bool someClass::doSomething(someParam a)
    {
        return true;
    }
}

namespace v2 {

    class someParam : public v1::someParam {
    public:
        bool doParamStuff();
    };
    bool someParam::doParamStuff()
    {
        return true;
    }
}

// Type Aliasing for v2 API
using someClass = v1::someClass;
using someParam = v2::someParam;

// SOME OTHER PROGRAM
class plugin : public someClass
{
public:
    plugin() {};
    virtual ~plugin() {};
    bool doSomething(someParam a) override;

};
在这个特定的例子中,我们正在创建现有类的扩展,以允许二进制兼容性。尽管如此,由于override关键字,我们得到了plugin::doSomething的编译错误,因为它没有覆盖someClass::doSomething,因为:

plugin::doSomething(v2::someParam)与someClass::doSomething(v1::someParam)的比较。

有没有办法修复插件而不在插件类中明确使用v1 for someParam?理想情况下,在插件端不应该做任何事情,也不必创建v2::someClass

virtual bool doSomething(::v1::someParam a)
指定二进制(和C++)接口。您不能用

virtual bool doSomething(::v2::someParam a)
因为那是另一种类型。它们不兼容。这些签名是无关的

更新
someParam
时,还必须更新使用
someParam
的每个接口,然后更新使用这些接口的每个接口,以此类推

因此,在
命名空间v2
中:

class someClass: ::v1::someClass {
public:
    virtual bool doSomething(::v1::someParam a) override final;
    virtual bool doSomething(someParam a);
};
doSomething(v1::someParam)
中,描述如何生成
v2::someParam
并将其传递给新的
doSomething

如果您无法做到这一点,则必须做到:

class someClass {
public:
    virtual bool doSomething(someParam a);
};
并使
v2::someClass
成为与
v1::someClass
无关的类型

不管怎样,你会的

using someClass = v2::someClass;
现在,您可以有条件地使用
inlinenamespace
s,而不是使用
using
声明

更新版本时,将当前版本设为
内联
命名空间。其他名称空间是普通名称空间

代码现在将以静默方式开始使用“当前”的内联命名空间

您可以通过
使用symbol=::library\u ns::v1::symbol从以前的名称空间导入类型仅当该类型及其所有参数保持不变时,才应执行此操作


现在,如果您的
::v2::someParam
只是一个助手,那么您可以从
someparampinstance
类型中拆分
someParamArg

someParamArg
将是
someParam
继承权(
::v1::someParam
)根的参数类型,而
someParamInstance
将是
::v2::someParam
;当人们想要使用它时,他们应该创建什么

在此情况下,<>代码>某些PARAMARG 需要考虑代码的每一个状态>某些PARAMPAST/<代码>,甚至是那些后来版本的代码。因此,只有当

::v2::someParam
本质上是一个助手,或者它支持内部值类型多态性时,这才有效