C++中虚函数实现不起作用

3

我是C++的新手,我试图编写一个简单的代码来比较一个被称为Comparable的父类的两个子类对象。 我希望每个子类都有自己的实现方法,根据它们持有的数据比较对象,所以我使用了virtual关键字:

class Comparable {  
public:
virtual int compare(Comparable *other); 
    };

例如,我的子类HighScoreElement将有自己的compare方法实现,将比较对象的得分和另一个HighScoreElement的得分。
这是我的子类HighScoreElement:
class HighScoreElement: public Comparable { 
        public: 
virtual int compare(Comparable *other); 
HighScoreElement(string user_name, int user_score); // A constructor
        private: 
int score; 
string name;

 };

但是在HighScoreElement中的比较实现中,我首先尝试检查当前对象的数据是否与其他数据相同。但由于指向其他Comparable类而不是HighScoreElement类的指针,我无法在代码中引用other->score,尽管HighScoreElement是Comparable的子类。

以下是迄今为止的全部代码:

#include <iostream> 
using namespace std; 

class Comparable {
public: 
virtual int compare(Comparable *other);
    };

class HighScoreElement: public Comparable {
public: 
    virtual int compare(Comparable *other);
    HighScoreElement(int user_score, string user_name);
private:
    string name;
    int score; 
};

HighScoreElement::HighScoreElement(int user_score, string user_name) {
name = user_name; 
score = user_score; 
}



int HighScoreElement::compare(Comparable *other) {
if (this->score == other->score) { // Compiler error right here, other->score is invalid.
    // Code to do the comparing if two scores are equal...
}
}

当我写下这段代码时,编译器立即报错:

if (this->score == other->score)

因为其他数据没有称为“分数”的数据,但它的子类HighScoreElement有。我该如何修复我的函数实现,以便我可以引用“其他”的数据?我知道我的问题可能听起来含糊不清,但任何帮助都将不胜感激!


一个简单的解决方案是使用 dynamic_cast<HighScoreElement*>(other),如果 other 没有指向 HighScoreElement 的实例(或其派生类),则返回 nullptr0)。不过可能存在更好的设计,可以避免使用 dynamic_cast - dyp
2
不是针对个人,但这段代码很丑。看起来像是一种使用Comparable作为接口的Java风格的C++代码?我的心都碎了。 - kvv
我的代码在我开始使用C++的时候很糟糕。 学习过程就像走在泥泞的道路上一样。人们的代码质量随着时间的推移而得到改善。 - Jamin Grey
1
是的,我是一个完全的初学者,我知道代码非常丑陋,但这只是为了学习目的。因此我的问题 :) - ra1nmaster
@Jamin Grey 我不能不同意。 - kvv
4个回答

1
你可以在基类中实现一个虚函数GetScore(),可能是pure virtual,并在比较函数中使用它而不是访问score字段。将其作为const方法。另一方面,Compare可以是在基类中实现的方法,它使用this->GetScore()other->GetScore()
代码框架:
class A {
   virtual int getScore() const = 0;
   inline bool compare(const A* in) {return (in && this->getScore() == in->getScore());}
   //return false also if "in" is set to NULL
   }


class B : public A {
   int score;
   inline int getScore() const {return score;}
   }

谢谢您的输入!现在我知道该如何实现它了。 - ra1nmaster
我重写了我的代码,这样其他人就可以使用一个纯虚拟的getScore函数来返回正确的分数值。 - ra1nmaster

0

您可以使用 "dynamic_cast" 将传递给 HighScoreElement::compare 的指针进行转换(如果失败,它会抛出 bad_cast 异常)。

int HighScoreElement::compare(Comparable *other) {
HighScoreElement *h = NULL; 
try
{
    ptr = dynamic_cast<HighScoreElement *>(other); 
}
catch(std::bad_cast const &)
{
    // Handle the bad cast...
}
if (this->score == ptr->score) { 
// Code to do the comparing if two scores are equal...
}
}

[expr.dynamic.cast]/9:“将类型转换失败的指针类型的值是所需结果类型的空指针值。将类型转换失败的引用类型抛出异常[...]” - dyp

0

如果你准备接受空指针,你可以使用动态转换。你可以为比较HighScoreElement指针的情况重载,以避免不必要的转换。

#include <iostream> 
using namespace std; 

class Comparable {
public: 
  virtual int compare(Comparable *other) = 0;  // made pure virtual to compile without definition
};

class HighScoreElement: public Comparable {
public: 
  virtual int compare(Comparable *other);
  int compare(HighScoreElement *other); // comparing to a HighScoreElement ptr, no need to dynamic cast
  HighScoreElement(int user_score, string user_name);
private:
  string name;
  int score; 
};

HighScoreElement::HighScoreElement(int user_score, string user_name) {
  name = user_name; 
  score = user_score; 
}

int HighScoreElement::compare(Comparable *other) {
  HighScoreElement * pHSE = dynamic_cast<HighScoreElement*>(other);
  if (pHSE) {
    return compare(pHSE);
  } else {
    return -1; // or however you want to handle compare to non HighScoreElement
  }
}

int HighScoreElement::compare(HighScoreElement *other) {
  if (this->score == other->score) {
    ;
  }
}

@DyP 谢谢。似乎我永远无法做到100%正确。已更正。 - A.E. Drew
请注意,您还应更改代码,因为它当前包含可能的访问冲突(由于没有异常,other->score 可能在 nullptr 上操作)。调度很好;如果 dynamic_cast 返回 0,则对象不相等。但是请注意,other 可能是从 HighScoreElement 派生的,因此仅检查 score 可能不足够。 - dyp

-1

你确定不是

compare( Comparable other )

如果 (this->score == other.score)


Comparable 不包含名为 score 的成员,而您的建议将切片任何派生自 Comparable 的传递对象。 - dyp
我认为这里有些混淆了。OP可能将实现Comparable接口与使用Comparable作为要传递的类型混淆了。 - Andyz Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接