1

我目前正在为现有类编写一个包装器。在不更改直接使用现有类的任何客户端代码的情况下编写包装器的最佳方法是什么?

class A
{
public:
    void foo() {}
};

template<typename T>
class Wrapper
{
// ...other wrapper data/functionality...
private:
    T myObject;
};

main()
{
    Wrapper<A> wrappedA;
    wrappedA.foo();
}

在 msvc 中编译失败并出现错误 C2039:“foo”:不是“Wrapper”的成员

在不更改 main 中的任何代码的情况下使模板包装类工作的最佳方法是什么?

  • 选择运算符。不能超载
  • 将强制转换运算符写入类型 T 没有帮助,因为编译器在进行选择之前不会尝试强制转换
  • 我们可以编写一个 get 函数来返回内部的 myObject 成员,但 main 中的客户端代码必须重写。如果有大量现有代码直接使用 myObject 而没有我们正在尝试编写的新包装类,这并不好。

编辑

  • 我想在 myObject 上编写一个包装类,而不必更改任何直接使用 myObject 的现有客户端代码
  • A::foo() 不能被带入包装器,因为其他类型 T 可能没有 T::foo()
4

3 回答 3

3

您需要通过A实例调用它:

wrappedA.myObject.foo();

您的包装器不是一个非常聪明的包装器,因此您需要知道它包含一个名为myObject. 您可以通过给它一个转换运算符使它变得聪明:

template<typename T>
class Wrapper
{
public:
    T myObject;

    operator const T& () const { return myObject; }
    operator T& () { return myObject; }
};

这将允许您在需要 an 的地方使用它A

void bar(const A& a) { a.foo(); } // (make A::foo() a const method)

Wrapper<A> a;
bar(a);  // OK 
于 2013-10-28T07:02:50.427 回答
2

如果必须使用 -> 访问方法不是问题,则提供 operator-> 返回指向包装类的指针:

template
class Wrapper
{
public:
  T* operator->() { return &myObject; }
  T const* operator->() const { return &myObject; }
...
};

但是如果你真的想用 dot 来访问方法,那么也许从 T 派生 Wrapper?(但是你的课程根本不是一个包装器:D)

于 2013-10-28T07:01:14.547 回答
2

使用wrappedA.myObject.foo();而不是wrappedA.foo();

于 2013-10-28T07:06:06.630 回答