c++ - 使用继承而不是 typedef 来实现前向可声明性和回调带来的复杂性

标签 c++ c++11

不太确定如何在此处表述标题。

问题是我有一个类模板:

template<various parameters> struct Base { ... };

然后我有一组从中派生的开放类:

struct A: public Base<some arguments> { ... };
struct B: public Base<other arguments> { ... };
struct C: public Base<different arguments> { ... };
...

重要的是,派生类除了固定模板参数之外没有向 Base 添加任何内容——不是成员函数,尤其是成员变量。所以他们的二进制表示应该都是一样的。我使用继承而不是 typedef 的唯一原因是我希望能够前向声明 A、B、C 等(或者更准确地说,A、B、C 等由客户使用提供的宏,为了他们的方便,我希望他们能够前向声明。)拥有 A、B、C 等的原因是为了避免必须写出始终手动模板参数。

问题是 Base 有一些函数将回调作为参数,并且回调应该将对类本身的引用作为参数。

所以我希望有像这样的回调函数:

void foo (A&, ...);
void bar (B&, ...);

等等。在 Base 中实现回调函数时,我想将 *this 作为参数传递给回调。很明智地,C++ 不允许我这样做,因为在预期派生类的地方传递基类通常是不安全的。但在这种特定情况下,这应该不是问题,因为派生类不会向基类添加任何内容,而只是用来代替 typedef。

看来我有三个标准:

  • 我希望“typedef”是前向声明的。
  • 我需要能够将基类传递给回调。
  • 我希望能够使用“typedef”而不是基类来声明回调。

两者互不相容。 (第三个标准再次是为了客户的方便,因为每次都将模板参数手动写到基类中会非常冗长,而不想这样做是拥有'typedefs的全部原因'.)

我看到三种解决方案:

  • 放弃第一个或第三个标准。

  • 某种丑陋而复杂的方案,我检查回调函数需要什么样的参数,并验证它是基类的伪类型定义(通过检查 sizeof 是否相同以及通过 SFINAE 确定它是从基础派生,或检查由生成伪 typedef 的宏插入的某种标记,或类似的东西),然后执行强制转换。

还有更好的吗?

(允许使用 C++11。)

最佳答案

雇用CRTP idiom并在模板参数中也传递派生类。对于回调,只需将 *this 转换为派生类型即可。

template<class Derived, other params...>
struct Base{
    template<class F>
    void do_callback_stuff(F func){
        func(static_cast<Derived&>(*this), ....);
    }
};

struct A : public Base<A, other args...>{};

关于c++ - 使用继承而不是 typedef 来实现前向可声明性和回调带来的复杂性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8175155/

相关文章:

c++ - 连接两个流函数 c++

c++ - fork 命令是否适用于多线程应用程序?

c++ - 如何将 C++ 对象返回到 lua 5.2?

c++ - std::basic_ifstream 抛出 std::bad_cast

c++ - C++11 中的函数返回函数指针

c++ - 如何清理或销毁QJSEngine?

c++ - 在不弹出每个元素的情况下显示使用 C++ STL 创建的堆栈的更好方法是什么

c++ - 为什么 GCC 中 std::list O(n) 的 size() 方法?

c++ - RapidXML 提供空 CDATA 节点

c++ - 如何告诉 gcc 显示您使用的优化标志列表