C++:从抽象类重写纯虚拟运算符重载



我在学校的作业要求我为虚拟运算符重载构建一个抽象类,然后构建一个使其工作的类。 具体来说:可比的 - 摘要

class IComparable{
public:
virtual bool operator== (const IComparable&) const = 0;
virtual bool operator< (const IComparable&) const = 0;
virtual bool operator> (const IComparable&) const = 0;
virtual bool operator!= (const IComparable&) const = 0;
virtual bool operator<= (const IComparable&) const = 0;
virtual bool operator>= (const IComparable&) const = 0;
};

和日期 - 实际类

class Date : public IPrintable, IComparable {
private:
int day;
int month;
int year;
public:
Date(int, int, int);
void setDay(int);
void setMonth(int);
void setYear(int);
bool Comparison(const Date&, const Date&) const;
bool larger(const Date&, const Date&) const;
bool operator== (const IComparable& other)const override;
bool operator< (const IComparable& other)const override; 
bool operator> (const IComparable& other)const override;
bool operator!= (const IComparable& other)const override;
bool operator<= (const IComparable& other)const override;
bool operator>= (const IComparable& other)const override;
~Date();
};

当我尝试在Date中实现它时出现问题.cpp

我真的不知道该怎么做。

我认为我应该使用 dynamic_cast 将 IComparable 向下转换为 Date 以在函数中使用。 但是我遇到了问题。我尝试了几种不同的实现,我将把它们扔在这里,以防万一其中一个接近我必须做的事情。

bool Date::operator< (const IComparable& other)const override  {
Date *D1 = dynamic_cast<Date*>(other);
return(larger(*this,*D1);
}

bool Date::operator> (const IComparable& other)const override{
return(larger(other, *this));
}
bool Date::operator!= (const IComparable& other)const {
bool Flip;
Flip = Comparison(*this, other);
return(!Flip);
}

我需要键入覆盖吗?因为它显示为错误"预期 {">

总的来说,我做错了什么。 提前谢谢。

你永远无法将具体的东西与抽象的东西进行比较。这就像问"这本书和一般的阅读材料哪个更贵?
要解决这个问题,你需要使这两个论点都具体化。

执行此操作的正常方法是使用称为双重调度的模式。
拿这条线...

bool operator== (const IComparable& other)const override;

你怎么可能实现这个功能?想想吧。该函数知道"this"是一个日期,但其他是什么?它可以是从IComparable派生的任何内容。关于自身,IComparable唯一声明的是可比性。

在双重调度中,您使用每个函数都必须知道其自己的类型这一事实。然后,它对第二个参数调用一个具体的比较方法,并将其作为参数传递。然后,此函数知道两个参数的类型,并可能解决问题。
这显示在上面的维基百科页面上的"C++双重调度"下。

你的第一次尝试几乎是正确的

bool Date::operator< (const IComparable& other) const { // no override in out-of-line definition
const Date *D1 = dynamic_cast<const Date*>(&other); // cast pointer to other, retaining constness
// throw if D1 == nullptr?
return larger(*this,*D1);
}

或者,您可以

bool Date::operator< (const IComparable& other) const { // no override in out-of-line definition
const Date& D1 = dynamic_cast<const Date&>(other); // will throw if other isn't a Date
return larger(*this, D1);
}

请注意,仅实现<<=>和类似>=中的一个很有用。其余的可以按照这个来实现。这样可以更容易不犯错误。

bool Date::operator<= (const IComparable& other) const {
return !(other < *this);
}
bool Date::operator> (const IComparable& other) const {
return other < *this;
}
bool Date::operator>= (const IComparable& other) const {
return !(*this < other);
}

你也可以在<方面实现==!=,尽管如果你有不平等的捷径,最好自己实现==

bool Date::operator== (const IComparable& other) const {
return !(*this < other) && !(other < *this);
}
bool Date::operator!= (const IComparable& other) const {
return !(*this == other);
}
return(larger(*this,*D1);

这是一个相当明显的语法错误 - 不匹配(. 先解决此问题。

要从dynamic_cast运算符获取指针,我们需要传入一个指针(使用 address-of 运算符&(。 此外,使用dynamic_cast而不检查结果的有效性几乎没有意义 - 如果other不是Date,我们会得到nullptr

bool Date::operator< (const IComparable& other) const
{
auto *other_date = dynamic_cast<const Date*>(&other);
if (!other_date) { return false; }
return larger(*this,*other_date);
}

或者,我们坚持使用引用,但捕获std::bad_cast异常而不是测试 null:

bool Date::operator< (const IComparable& other) const
{
try
auto &other_date = dynamic_cast<const Date&>(&other);
return larger(*this,other_date);
} catch (std::bad_cast&) {
return false;
}
}

请注意,这两个版本仍然很差,因为我们在这里没有提供所有IComparable对象的良好总排序 - 这是此类接口在C++中是一个坏主意的主要原因(也许这是这里教学的教训?(。

我找到了另一种处理这个问题的方法,这很有意义。 我们将 IComparable 转换为如下所示的模板类:

template<typename T>
class IComparable{
public:
virtual bool operator== (const T&) const = 0;
virtual bool operator< (const T&) const = 0;
virtual bool operator> (const T&) const = 0;
virtual bool operator!= (const T&) const = 0;
virtual bool operator<= (const T&) const = 0;
virtual bool operator>= (const T&) const = 0;
};

然后用 IComparable 声明日期 这样,我们就可以让 Comparable 充满纯虚拟,并且不会受到整个dynamic_cast问题的困扰

class Date : public IPrintable<Date>, IComparable<Date> {
.
.
.
bool larger(const Date&, const Date&) const;
bool operator== (const Date &other)const;
bool operator< (const Date &other)const;
.
.

来自 cppreference.com

dynamic_cast<新型>( 表达式 (

如果强制转换成功,dynamic_cast返回 newtype 类型的值。如果强制转换失败并且 new-type 是指针类型,则返回该类型的 null 指针。如果强制转换失败并且 new-type 是引用类型,则会引发与类型为 std::bad_cast 的处理程序匹配的异常。

最新更新