C++11 C++;使用名称空间进行版本控制可能会导致重写的继承问题
我们正在尝试使用名称空间为API的版本命名,尽管我们认为虚拟函数会出现一些问题: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() {};
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
本质上是一个助手,或者它支持内部值类型多态性时,这才有效