我可以避免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++类。
然后让我们考虑整数与有理数。有理数只是一个整数除以另一个分数,并且可以指定为一对整数 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
,但是当您将Integer
与Rational
进行比较时,只有用于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;
}
}
好处(但可能是有争议的(是它不会针对未提供专用化的类型进行编译。
- C++方法实现:是否可以避免每次都键入类名?
- 是否可以避免在以下代码中复制/移动构造函数的需要?
- 我可以避免通过time_t打印时间点吗
- 有什么技巧可以避免在模板类中使用"typename"关键字吗
- 在这种情况下,我可以避免使用带有主体的纯虚函数吗?
- 是否可以避免将参数复制到 lambda 函数?
- 是否有一种方法可以避免标头文件中使用的constexpr函数输入全局范围,而无需额外的名称空间
- 如果BOOL仅从false到true一次,我可以避免锁定布尔
- 是否有一种方法可以避免在RVALUE和LVALUE参考中创建功能时避免重复的代码
- 在这种情况下是否可以避免使用虚拟方法调用?
- 是否可以避免在前向声明中使用嵌套命名空间?
- 使用GCOV时,是否有一种方法可以避免使用CPP文件中包含的标头文件进行仪器
- 是否可以避免 for 循环来计算矩阵条目
- 在Thrift中,有没有一种方法可以避免生成C++setter
- 我可以避免在std ::变体中明确编写每个结构的构造函数
- 是否可以避免使用lambda中的尾随返回型语法
- 在GPU上调用函数时,我可以避免__device__限定符吗
- 我是否可以避免由特定类定义的限定名称
- 我是否可以避免模板化需要模板化成员的类
- 我可以避免RTTI吗?