我有一个公开的接口A
和一个后端实现类C
,如下所示:
struct A
{
virtual void f() = 0;
};
struct C : public A
{
virtual void f() override
{
}
};
我想逐步迁移到新界面B
。 B
将使用相同的方法,但返回类型可能不同。我希望我的实现类实现A
和B
,以便遗留代码可以继续使用A
,直到迁移,但新代码可以用B
编写。我知道如果我有两个具有完全相同签名的纯虚方法,我在实现类中只需要一个覆盖。但如果他们的回报类型不同,我就不知道怎么做......
struct A
{
virtual void f() = 0;
};
struct B
{
virtual int f() = 0;
};
struct C : public A, public B
{
// How do I implement both versions of f() here??
};
答案 0 :(得分:0)
这至少与VS2017编译:
struct A
{
virtual void f() = 0;
};
struct A2: public A
{
void f() { Af(); }
virtual void Af() = 0;
};
struct B
{
virtual int f() = 0;
};
struct B2 : public B
{
int f() { return Bf(); }
virtual int Bf() = 0;
};
struct C : public A2, public B2
{
void Af() {}
int Bf() { return 42; }
};
编辑:无法在Paul Accisano自己的回答中添加评论,所以我把它放在这里。
略微修改保罗的答案。通过使未使用的默认参数成为受保护的类,您仍然可以进行正确的类型检查,并避免与另一个成员函数发生类型冲突。
struct A
{
virtual void f() = 0;
};
struct B
{
protected:
class disambiguator {};
public:
virtual int f(disambiguator ignoreMe = disambiguator()) = 0;
};
struct C : public A, public B
{
virtual void f() override {}
virtual int f(disambiguator ignoreMe) override { return 42; }
};
A *createA() { return new C; }
B *createB() { return new C; }
这方面的一个应用可能是从原始指针到智能指针的逐步迁移。
答案 1 :(得分:0)
我这样做的方式是
struct A {}
struct B {}
struct OldImpl : public A {}
struct NewImpl : public B {}
struct Combined : public AImpl, public BImpl {}
然后你可以将组合传递给想要A或B的任何东西。
这个问题是你的OldImpl和NewImpl完全是分开的。他们不允许彼此互动;这意味着您无法在A中调用setFoo()
并在B中的getFoo()
中获得相同的值。这可能与您所描述的不同。
要解决此问题,请不要创建第二个界面。它无论如何都不会起作用,因为现在xxx()
可能无效,而后来的int,你可能想要对返回值做一些事情。如果你真的想在婴儿步骤中做,请创建一个分支,更改单个函数返回值,测试它,合并它,重复。
答案 2 :(得分:0)
感谢您的好评!但我确实找到了自己的解决方案:好的旧可选参数!
struct A
{
virtual void f() = 0;
};
struct B
{
virtual int f(int ignoreMe = 0) = 0;
};
struct C : public A, public B
{
virtual void f() override {}
virtual int f(int) override {}
};
使用A
或B
的外部用户没有歧义,也不需要更改任何参数。内部没有歧义,因为参数在实现类中是非可选的。迁移完成后,可以删除可选参数以及A
。