模板化虚拟函数替代项

问题描述 投票:0回答:3

模板虚拟函数有哪些替代方案?

这里是我的安装案例的抽象:

class CParent
{
    bool m_bExampleParentData = true;

public:
    template< typename t > virtual operator t( ) = 0;
};

class CChild1: public CParent
{
    char m_chExampleChild1Data = 'c';

public:
    operator char & ( ) override
    {
        return m_chExampleChild1Data;
    }
};

class CChild2: public CParent
{
    int m_iExampleChild2Data = 17;

public:
    operator int & ( ) override
    {
        return m_iExampleChild2Data;
    }
};

这里是我用例的抽象:

int main( )
{
    std::vector< CParent * > vecAbstractPointers;

    CChild1 child1;
    vecAbstractPointers.emplace_back( reinterpret_cast< CParent * >( &child1 ) );
    CChild2 child2;
    vecAbstractPointers.emplace_back( reinterpret_cast< CParent * >( &child2 ) );

    *vecAbstractPointers[ 0 ] /*char( child1 )*/ = 'b';
    *vecAbstractPointers[ 1 ] /*int( child2 )*/ = 8;
}

我敢肯定有些东西比这段代码更明显,更简单,但是我一生都想不到。

这有望实现通过父类中的虚拟函数分配子类成员的能力,而无需了解子类成员的类型。我认为自己没有什么可以做的,我也许可以使用标准(例如std::variantstd::any)来实现某些功能,但我想避免这种情况。我试图使结束代码尽可能不进行转换(因此进行隐式转换)。

c++ oop types c++17
3个回答
1
投票

在不知道子类成员类型的情况下,通过父类中的虚拟函数分配子类成员

这在C ++中通常是不可能的。 C ++是一种静态类型的语言。因此,必须在编译时知道每个表达式的类型。模板也遵循此规则。它们只是允许根据特定类型生成函数/类/等。因此,对于带有类型参数T的模板函数,可以生成无限数量的可能函数。编译器仅生成静态使用的代码。

这是静态多态性。

此模板生成函数也是为什么不允许virtual模板函数的原因。根据定义,它们必须有无限多个版本,并且派生类必须实现每个版本。 virtual机制通常依赖于函数的身份,而对于模板而言,它实际上并不存在。

virtual函数表示动态/运行时多态性。这些基于在基类中定义的原型,这些原型在派生类中实现。但是那些原型只是regular functions。具有完整功能签名(包括其返回类型)的功能。必须遵循C ++规则的签名:类型在编译时是已知的。

因此,实现您所讨论内容的唯一方法是将值打包,以使编译器不知道类型是什么,而源和目标却知道。 std::any是一个不错的工具。


1
投票

这是我想出的,只需要对您发布的代码进行最小的更改。

#include <iostream>
#include <vector>

// Base class to be able to hold pointers to derived class instances.
class CParent
{
   bool m_bExampleParentData = true;
   public:

      // Add this to make sure deleting object through base class pointers works
      // as well as dynamic_cast is supported.
      virtual ~CParent() {}
};

// Base class to allow inheritance of specific conversion operators.
template <typename T>
class TParent
{
   public:
      virtual operator T() = 0;
};

// By inheriting from TParent<char&>, this class must support conversion
// to char& to allow instantation of class objects.
class CChild1: public CParent, public TParent<char&>
{
    char m_chExampleChild1Data = 'c';

    operator char & ( ) override
    {
        return m_chExampleChild1Data;
    }
};

// By inheriting from TParent<int&>, this class must support conversion
// to int& to allow instantation of class objects.
class CChild2: public CParent, public TParent<int&>
{
    int m_iExampleChild2Data = 17;

    operator int & ( ) override
    {
        return m_iExampleChild2Data;
    }
};

int main()
{
    std::vector< CParent * > vecAbstractPointers;

    CChild1 child1;
    vecAbstractPointers.emplace_back( reinterpret_cast< CParent * >( &child1 ) );
    CChild2 child2;
    vecAbstractPointers.emplace_back( reinterpret_cast< CParent * >( &child2 ) );

    // Rather ugly casts to allow assignment of 'b' and 8.
    static_cast<char&>(*(dynamic_cast<TParent<char&>*>(vecAbstractPointers[0]))) = 'b';
    static_cast<int&>(*(dynamic_cast<TParent<int&>*>(vecAbstractPointers[1]))) = 8;

    // Rather ugly casts to allow extraction of 'b' and 8.
    std::cout << static_cast<char&>(*(dynamic_cast<TParent<char&>*>(vecAbstractPointers[0]))) << std::endl;
    std::cout << static_cast<int&>(*(dynamic_cast<TParent<int&>*>(vecAbstractPointers[1]))) << std::endl;
}

PS请不要在实际应用中使用此类代码。我相信您要完成的工作会有更好的设计。


0
投票
class CParent
{
  bool m_bExampleParentData = true;
public:
  virtual operator int&( ) { exit(-1); }
  virtual operator bool&( ) { exit(-1); }
};
template<class T>
class Child:public CParent
{
  T t;
public:
  operator T&() override { return t; }
};
using CChild1=Child<int>;
using CChild2=Child<bool>;

然后:

std::vector< CParent * > vecAbstractPointers;

CChild1 child1;
vecAbstractPointers.emplace_back( &child1 );
CChild2 child2;
vecAbstractPointers.emplace_back( &child2 );

*vecAbstractPointers[ 0 ] /*char( child1 )*/ = 'b';
*vecAbstractPointers[ 1 ] /*int( child2 )*/ = 8;

编译。

这是一个坏主意。

© www.soinside.com 2019 - 2024. All rights reserved.