我可以避免 RTTI 吗?

Can I avoid RTTI?

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++ classes 表示不同种类的数字,具有继承关系。

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

因此,每个整数 都是一个 有理数。有理数值集,包括作为真子集的整数值集。

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

幸好有一条出路:不使用 class 继承,而是 隐式转换 ,来模拟逻辑 is-a 关系。

然后我们将 Integer 作为一个不同的且首先定义的 class,将 Rational 作为第二个定义的 class,并使用一个构造函数将 IntegerRational (通过采用 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);
}

您还可以 google double dispatch 主题了解更多信息

你的情况

不要忘记以相反的方式进行比较,因为我们是从右侧执行的

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

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