【问题标题】:C++ Generic wrapper class which adds extra processing for some functionsC++ 通用包装类,为某些函数添加额外处理
【发布时间】:2018-07-25 12:37:21
【问题描述】:

我正在尝试为传统继承层次结构创建一个包装类,它不是严格多态的。在包装类中,我为一些方法添加了额外的功能,但对于许多其他方法,我只想调用包装类的方法。

我想知道是否有一种方法可以在包装器类中编写一个通用包装器函数,这将允许我以正常方式调用包装器函数,就好像没有包装器类一样。 可能是我错了,但我不认为重载 operator-> 会起作用,因为包装类的一些方法,我想在调用包装类函数之前对其进行一些处理(尽管对于许多其他人,我不不需要这样做)。 我还查看了 Herb Sutter 的包装模式(同样,我可能错了),但这需要我有一个 lambda 才能访问包装的函数。 我想知道是否有人对这是否可以实现有任何想法?

我已经放了代码@cpp.sh/2ombu
在这里而不是
wrapper->operator()([](Derived& x)
{
   x.print();
});

wrapper->operator->()->print();

有没有办法让我拥有

wrapper->print();

提前感谢您的回答..

【问题讨论】:

  • "但这需要我有一个 lambda" - 你永远需要一个 lambda。 lambda 只是经典函数对象的语法糖。您始终可以编写经典的 C++98 代码来获得与 lambda 相同的效果(只是更冗长)。
  • 您应该在问题中以文本形式提供代码,而不是通过外部链接!
  • 请看this answer的讨论,也许您可​​以更准确地了解您真正想要实现的目标?
  • @Aconcagua - 当然,下次会在问题中发布代码。是的,正如@Jarod42 所说,我的问题是指针的使用。一旦我做了他建议的更改,我现在可以将函数调用到包装类,而无需显式使用 operator-> 。谢谢
  • @Joseph 您确实在包装类中添加了新功能吗?然后考虑 Jarod 的 get() 方法,仅在对象上使用的运算符上选择 print 的一个或另一个变体是很危险的:wrapper->print(获取原始打印)与wrapper.print()(获取更改的一个)。使用指针((*wrapper)->print() vs. wrapper->print())会更明显,但我仍然不能推荐它......

标签: c++ c++11 c++14 generic-programming


【解决方案1】:

你的问题是你实际上使用了指针。

目前,而不是

wrapper->operator->()->print();

你可以写

(*wrapper)->print();

如果你替换了不需要的指针

wrap<Derived> *wrapper = new wrap<Derived>(der);

通过

wrap<Derived> wrapper(der);

那么,你可以替换

wrapper->operator->()->print();

通过

wrapper->print();
// or wrapper.operator->()->print(); :)

同理

wrapper->operator()([](Derived& x)
    {
       x.print();
    });

会变成

wrapper(([](Derived& x)
    {
       x.print();
    });

【讨论】:

  • 如果不替换: (*wrapper)->print() 应该也可以,不是吗?
  • @Aconcagua:是的,添加了。
  • 不过,我们总是使用 T 的打印功能。什么,如果包装要改变打印?那么我们可以同时调用wrapper.print()(已更改)和wrapper-&gt;print()(未更改)吗?不想进一步评论...(旁注:任何-&gt;print() 变体都不要使用Wrapperoperator()。)
  • @Aconcagua:正如 OP 所写,wrapper-&gt;f(..) 调用常规的 Derived 函数,而 wrapper.f(..) 会添加专用的东西(每个函数:wrapper "redefines" prettyPrint 但不是 print) 并调用 Derived 函数。如果它是通用的,我会用wrapper-&gt;f() 来获取额外的东西,wrapper.get().f() 来进行常规调用。
  • .f().get().f() 至少可以很清楚地说明实际调用的内容,而仅使用 .-&gt; 则相反。我理解这个问题应该是透明的(总是使用 .f() 或 ->f(),使用更改后的变体,如果存在的话,或者使用原来的变体。通常简单地通过继承解决,但来自 "哪个不是严格多态的” 我的结论是有非虚拟函数也应该改变?假设 OP 应该添加一些细节来提问......
【解决方案2】:

不能完全给你想要的结果,但仍然相对便宜(就必须编写的代码而言):继承:

class Wrapped
{
public:
    void f();
    void g();
};

class Wrapper : private Wrapped
{
public:
    // replacing Wrapped's f with own variant:
    void f() { pre(); Wrapped::f(); post(); };
    // pulling Wrapped's g into public  domain again:
    using Wrapped::g;
};

所以你所要做的就是添加相应的using 声明。如果您现在问:“为什么不公开继承,那我就不必了?”,那么请考虑以下问题:

Wrapped* w = new Wrapper();
w->f(); //Wrapped's version of f will be called, as f in given example is not virtual!

也许你会说“我永远不会直接使用Wrapped。”。这会奏效,但是仍然在某处使用它然后得到错误的危险仍然存在于公共继承中......

【讨论】:

    猜你喜欢
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-14
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多