如何使用隐式转换运算符模拟类行为

时间:2015-01-15 19:15:03

标签: c++ casting operator-overloading

假设有两个类,Foo和ImitateFoo。 ImitateFoo实现了一个隐式的强制转换运算符,就像Foo一样。

class Foo
{
public:
    int DoFoo() { return 1; }
};

class ImitateFoo
{
private:
    Foo f;

public:
    operator Foo&() { return f; }
};

我想对ImitateFoo采取行动,就像我在Foo上做的那样。特别是调用它的方法。

ImitateFoo imitator;

Foo& f = imitator; // implicit cast works
f.DoFoo();

static_cast<Foo&>(imitator).DoFoo(); // static cast works as well

imitator.DoFoo(); // does NOT compile -- desired behaviour!

不幸的是,最后一种方法无法编译(至少在VS 10.0中)。 由于某些原因,不能使.-运算符超载。

我有什么建议可以达到预期的行为吗?是否可能以某种方式增加cast-operator对。-operator的绑定优先级?

编辑:为什么我不能将继承用作最明显的解决方案

我必须重新实现一堆框架类。 Foo类似于其中一个,它在遗留代码中用作全局对象(我不能更改)。

由于我现在需要进行单元测试,我需要控制这些全局对象的状态。这与完成类似的方式完成 PIMPL idiom建议。

在这种情况下,ImitateFoo类只有一个状态:它的实现被注入并可能在运行时被更改。所有方法调用都会重定向到此Foo实例。所以实际上我可以实现上面的例子就像在DoFoo中创建一个ImitateFoo非虚函数一样简单,并重定向到其current实现方法。事实上,这就是我现在正在做的事情。

这对于方法和运营商都很有效。但是它导致了大量的膨胀代码,它不会重定向。

与通过它自己重定向每个方法和操作符调用相反,我想退后一步,看看是否可以让ImitateFoo表现得像它的底层实现。

2 个答案:

答案 0 :(得分:0)

在像Python这样的动态语言中,您可以将所有非明确定义的方法委托给另一个对象(此处为字段f)。但是AFAIK在C ++中是不可能的。

如果继承不是可接受的解决方案,您可以明确地委托您希望ImitateFoo进行处理的所有方法,使用duck typing而不是继承:

class ImitateFoo
{
private:
    Foo f;

public:
    operator Foo&() { return f; }
    int DoFoo() { return f.DoFoo(); } // explicit delegation
};

它不是你想要的那么自动,但至少是:

imitator.DoFoo(); 

将正确编译并运行。

答案 1 :(得分:0)

看起来有点像X Y问题,而你提出的解决方案虽然在概念上很优雅,但我不相信它在C ++中是可能的。

运行一个与你类似的问题我已经使用宏来隐藏重复的代码,在你的情况下将是转换(考虑到你想要避免的实际问题是重写每个函数/ operator,主要目标是减少要写入的代码量。)

这是一段代码段

#define CAST(x) (static_cast<Foo&>(x))
...
ImitateFoo f;
CAST(f).DoFoo();
相关问题