我可以避免RTTI吗?

Can I avoid RTTI?

本文关键字:RTTI 可以避免      更新时间:2023-10-16
class Number{
public:
    virtual int compare(const Number& rhs) =0;
}
class Number2 : public Number{
public:
    int compare(const Number& rhs){/* *** */ }
};
class Number3 : public Number{
public:
    int compare(const Number& rhs){ /* *** */  }

};

例如。

Number2 f,s;
Number& ref  = f;
ref.compare(s);

因此,它调用 Number2::compare(对 s 的引用是隐式向上转换的(但这是一个问题,因为我应该知道 s 的类型进行比较。

我可以避免RTTI吗?

有点不清楚你在追求什么,但显然你想将不同类型的数字表示为具有继承关系的C++类。

然后让我们考虑整数与有理数。有理数只是一个整数除以另一个分数,并且可以指定为一对整数 a/b。每个整数 x 等于一个有理数,即 x/1。

所以,每个整数都是一个有理数。有理数值集包括作为正确子集的整数值集。

C++表示 is-a 关系的常用方法是类继承。但在这里它产生了一个愚蠢的结果:Integer应该从Rational继承,所以每个Integer都是Rational。然而,通常,Rational实例需要保存两个整数来表示其值。使用建议的继承,Integer实例将保存一个始终为 1 的整数。更不用说这里根据派生类Integer来定义Rational的循环关系(当然,这可以通过引入Basic_integer来解决,它可以只是int的typedef,但仍然如此(。

令人高兴的是,有一条出路:不使用类继承,而是隐式转换,对逻辑 is-a 关系进行建模。

然后,我们将Integer为一个独特的和第一个定义的类,Rational作为一个第二个定义的类,有一个构造函数将Integer转换为Rational(通过接受Integer参数的简单方法(。为 Integer 定义的比较函数适用于Integer,但是当您将IntegerRational进行比较时,只有用于Rational的比较函数匹配,并且通过Integer的隐式转换调用。

这可以通过使用双重调度来完成

class Number {
  protected:
  virtual Number& operator+(const Integer&) = 0;
  virtual Number& operator+(const Complex&) = 0;
  virtual Number& operator-(const Integer&) = 0;
  virtual Number& operator-(const Complex&) = 0;
// For all inherited types
  public:
  virtual Number& operator+(const Number&) = 0;
  virtual Number& operator-(const Number&) = 0;
};
class Integer : public Number {
  private:
  int I;
  protected:
  virtual Number& operator+(const Integer&);
  virtual Number& operator+(const Complex&);
  public:
  Integer(int x) : i(x) {}
  virtual Number& operator+(const Number&);
  // etc.
};
Number& Integer::operator+(const Number& n)
{
   return n + *this; // Replace rhs with lhs
}
Number& Integer::operator+(const Integer& n)
{
  // Here is some pseudocode
  if (i + n.i to big for int int) 
  {
    return LongInteger;
  }
  else 
    return Integer(i + n.i);
}

你也可以谷歌双重调度主题了解更多信息

在您的情况下

不要忘记在反向管理器中实现比较,因为我们从 RHS 方面执行

class Number2;
class Number3;
class Number{
    public:
    virtual int compare(const Number2& rhs) const = 0;
    virtual int compare(const Number3& rhs) const = 0;
    virtual int compare(const Number& rhs)  const = 0;
};
class Number2 : public Number{
protected:
    virtual int compare(const Number2& rhs)  const  { /* your implementation */ }
    virtual int compare(const Number3& rhs)  const  { /* your implementation */ }
public:
    int compare(const Number& rhs)  const {  return rhs.compare(*this); }
};
class Number3 : public Number{
protected:
    virtual int compare(const Number2& rhs)  const { /* your implementation */ }
    virtual int compare(const Number3& rhs)  const { /* your implementation */}
public:
    int compare(const Number& rhs)  const {  return rhs.compare(*this);  }
};

下面是一些示例代码

#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
class Number2;
class Number3;
class Number{
    public:
    virtual int opposite_compare(const Number2& rhs) const = 0;
    virtual int opposite_compare(const Number3& rhs) const = 0;
    virtual int compare(const Number& rhs)  const = 0;
};
class Number2 : public Number{
protected:
    virtual int opposite_compare(const Number2& rhs)  const;
    virtual int opposite_compare(const Number3& rhs)  const;
public:
    int m_Val;
    Number2(int a) : m_Val(a) { }
    int compare(const Number& rhs)  const {  return rhs.opposite_compare(*this); }
};
class Number3 : public Number{
protected:
    virtual int opposite_compare(const Number2& rhs)  const;
    virtual int opposite_compare(const Number3& rhs)  const;
public:
    int m_Val0;
    int m_Val1;
    Number3(int a, int b) : m_Val0(a), m_Val1(b) { }
    int compare(const Number& rhs)  const {  return rhs.opposite_compare(*this);  }
};
int Number2::opposite_compare(const Number2& rhs)  const  
{ 
    return m_Val == rhs.m_Val ? 0 : (m_Val > rhs.m_Val ? -1 : 1); 
}
int Number2::opposite_compare(const Number3& rhs)  const  
{ 
    return m_Val == (rhs.m_Val0 + rhs.m_Val1) ? 0 : (m_Val > (rhs.m_Val0 + rhs.m_Val1) ? -1 : 1); 
}
int Number3::opposite_compare(const Number2& rhs)  const 
{ 
    return (m_Val0 + m_Val1) == rhs.m_Val ? 0 : ((m_Val0 + m_Val1) > rhs.m_Val ? -1 : 1); 
}
int Number3::opposite_compare(const Number3& rhs)  const 
{ 
    return (m_Val0 + m_Val1) == (rhs.m_Val0 + rhs.m_Val1) ? 0 : ((m_Val0 + m_Val1) > (rhs.m_Val0 + rhs.m_Val1) ? -1 : 1); 
}
int main(){
 Number* pOne = new Number2(9);
 Number* pTwo = new Number3(6, 3);
 std::cout << "One comp Two: " << pOne->compare(*pTwo) << std::endl;
 delete pOne;
 delete pTwo;
return 0;
}

这实际上取决于您尝试解决的问题,特别是如果您确实需要多态层次结构。但是使用您提供的代码片段模板可能会有所帮助。也就是说,(例如(您声明了一个模板化比较帮助程序:

template<typename TNumber1, typename TNumber2>
class CompareHelper;

然后,您可以为不同类型的模板专业化,例如

template<>
class CompareHelper<int,double>
{
    static int compare(const int &i, const double &d)
    {
        // int to double comparision with an epsilon threshold
        return abs(i-d) < 1e-6;
    }
}

您可以将此比较帮助程序用作:

int i = 2;
double d = 2 + 1e-8;
int result = CompareHelper<int,double>(i,d);

编辑以下是 int-int 的比较,可能有助于理解这个概念:

template<>
class CompareHelper<int,int>
{
    static int compare(const int &i1, const int &i2)
    {
        // int to int
        return i1 == i2;
    }
}

好处(但可能是有争议的(是它不会针对未提供专用化的类型进行编译。