我可以避免RTTI吗?

时间:2015-10-12 18:58:42

标签: c++ 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的引用是隐式upcast) 但这是一个问题,因为我应该知道s的类型进行比较。

我可以避免使用RTTI吗?

3 个答案:

答案 0 :(得分:2)

有点不清楚你之后会发生什么,但显然你想用不同类型的数字表示C ++类,具有继承关系。

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

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

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

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

然后我们将Rational作为不同的第一个定义的类,Integer作为第二个定义的类,使用构造函数将Rational转换为Integer(通过采用Integer参数的简单方法。为Integer定义的比较函数适用于Integer,但是当您将RationalRational进行比较时,只有Integer的比较函数匹配,并且通过隐式转换if(condition){ function->setValue(true) } else{ function->setValue(false) }

来调用

答案 1 :(得分:1)

这可以通过使用双重调度

来完成
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主题获取更多信息

在你的情况下

不要因为我们从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;
}

答案 2 :(得分:1)

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

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

好处(但可能是有争议的)是它不会为没有提供专业化的类型进行编译。