c++ - C++中不带virtual的多态实现多级继承

标签 c++ templates polymorphism virtual function-pointers

我有一种情况,我需要在没有 vtable 的情况下实现多态性。这就是我正在尝试做的事情

  • 存在一个类层次结构:C 扩展 B,B 扩展 A
  • 其思想是在 A 中声明一个函数指针,然后 B 和 C 的构造函数将其相应的方法分配给 A 中的函数指针
  • 通过下面的代码,我能够实现 C 类的多态性,但不能实现 B 类的多态性。

显然我在这里遗漏了一些东西。我不确定这是否可能。非常感谢对此问题的任何见解。

我可以用下面的代码来做到这一点

A<C> *c = new C();
c->BasePrint(); //Reached C's Print

但不是这个

// A<B> *b = new B();
// b->BasePrint(); //Intentionally incorrect to demonstrate the problem.

有什么办法可以实现这一点吗?

template <typename T>
class A
{
public:
    typedef void (T::*PrintFn)(void);
protected:
    PrintFn printFn;
public:
    void BasePrint()
    {
        if(printFn)
            (((T*)this)->*printFn)();
    }
};


template <typename T>
class B : public A<T>
{
public:
    B()
    {
        printFn = &B::Print;
    }

    void Print()
    {
        //Print B
    }
};



class C : public B<C>
{
public:
    C()
    {
        printFn = &C::Print;
    }

    void Print()
    {
        //Print C
    }
};

最佳答案

#include <iostream>
#include <typeinfo>

struct own_type {};

template<template<typename T>class CRTP, typename In, typename D>
struct DoCRTP: CRTP<In> {};
template<template<typename T>class CRTP, typename D>
struct DoCRTP<CRTP, own_type, D>: CRTP<D> {};

template<typename D>
struct A {
   D* self() { return static_cast<D*>(this); }
   D const* self() const { return static_cast<D*>(this); }
   A() {
      std::cout << "A<" << typeid(D).name() << ">\n";
      self()->print();
   }
};

template<typename T=own_type>
struct B:DoCRTP<A, T, B<T>> {
   B() {
      std::cout << "B<" << typeid(T).name() << ">\n";
   }
   void print() { std::cout<<"I am a B\n"; }
};

template<typename T=own_type>
struct C:DoCRTP<B, T, C<T>> {
   C() {
      std::cout << "C<" << typeid(T).name() << ">\n";
   }
   void print() { std::cout<<"I am a C\n"; }
};

void test() {
   std::cout << "Instance of B<>:\n";
   B<> b;
   std::cout << "Instance of C<>:\n";
   C<> c;
}

int main() {
   test();
}

在这里,我们有一种方法可以传入最派生的类,如果您不传入任何内容,则假定您是最派生的类。

但是,您的设计存在问题 -- A已经完全知道它的类型情况,所以不需要虚拟行为! BasePrint可以static_cast<T*>(this)->Print()这样你就可以省掉你的开销。

您遇到的根本问题是您在基类中存储特定类型的成员函数指针 A .

无模板 A可以存储指向非特定类型函数指针的指针——比如显式采用 A* 的“静态”函数指针作为第一个参数。在 C++11 中,您可以从成员函数自动构建这些函数。在 C++03 中,std::bind应该让你将成员函数指针转换为 D到需要 A* 的函数作为第一个参数。

关于c++ - C++中不带virtual的多态实现多级继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15575869/

相关文章:

c++ - 有没有办法确定日期/时间是否不存在?

c++ - C++:遍历字符串 vector 并将索引用于putenv

c++ - g++-带有-O选项的浮点行为不是严格的C++11标准保形?

c++ - 自动扣除别名模板和模板类的模板参数

c++ - 在本地使用 reference_wrapper 初始化 vector

dynamic - FORTRAN 动态分配派生类型

ruby-on-rails - Rails Active Record 多态嵌套资源导航

c++ - C++ 程序员的 C 陷阱和错误

node.js - 我尝试了一切方法使该模板正常工作,但仍然出现此错误 : Only named blocks and mixins can appear at the top level of an extending template

c++ - 为模板类的实例分配唯一的数字标识符