C ++中没有虚拟的多态性,可实现多级继承 [英] Polymorphism without virtual in C++ for multi level inheritance

查看:105
本文介绍了C ++中没有虚拟的多态性,可实现多级继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到的情况是我需要在没有vtable的情况下实现多态.这就是我想要做的

I have a situation where I need to achieve polymorphism without vtable. Here is what I am trying to do

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

很显然,我在这里错过了一些东西.我不确定这是否可能.非常感谢您对此问题的见解.

Obviously I am missing something here. I am not sure if this is even possible. Greatly appreciate any insights into this problem.

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

I can do this with the below code

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

但不是这个

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

有什么办法可以做到这一点?

Is there any way to achieve this?

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();
}

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

Here we have a way you can pass in the most derived class, and if you pass in nothing you are assumed to be the most derived class.

但是,您的设计存在问题-A已经完全了解其类型情况,因此不需要虚拟行为! BasePrint可以static_cast<T*>(this)->Print(),您就可以省掉开销.

However, there is a problem with your design -- A already fully knows its type situation, so there is no need for virtual behavior! BasePrint could static_cast<T*>(this)->Print() and you'd do away with your overhead.

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

The fundamental problem you have is that you are storing specific-type member function pointers in your base class A.

无模板的A可以存储指向非特定类型函数指针的指针-说静态"的指针,显式地将A*作为第一个参数.在C ++ 11中,您可以从成员函数中自动构建这些函数.在C ++ 03中,std::bind应该允许您将成员函数指针转换为D转换为以A*作为第一个参数的函数.

A template-less A could store pointers to non-specific type function pointers -- say "static" ones that explicitly take an A* as the first argument. In C++11, you could auto-build these functions from member functions. In C++03, std::bind should let you convert your member function pointers to D to functions that take an A* as the first argument.

这篇关于C ++中没有虚拟的多态性,可实现多级继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆