【问题标题】:C++ can't override parent class methodC++ 不能覆盖父类方法
【发布时间】:2018-02-21 10:15:27
【问题描述】:

我在覆盖某个函数时遇到了一些问题,我不知道为什么它不起作用。我一直在网上寻找,但我没有找到任何东西。我可能应该补充一点,我现在正在使用 c++11 标准,以防万一。这是我的代码:

class SupervisedLearner {
public:
    ...
    virtual double measureAccuracy(Matrix& features, Matrix& labels, Matrix* pOutStats = NULL);
}

class NeuralNet: public SupervisedLearner {
public:
    ...
    double measureAccuracy(Matrix& features, Matrix& labels, Matrix* pOutStats = NULL) override;
}

然后通过指向通用 SupervisedLearner 类的指针调用方法 measureAccuracy:

SupervisedLearner* learner = getLearner(model, r, parser.getLearnerExtra());
...
double accuracy = learner->measureAccuracy(trainFeatures, trainLabels, &stats);

请注意,基类和子类都有该方法的实现。出于某种原因,该程序总是转到 SupervisedLearner::measureAccuracy 函数。

谁能看出明显的错误?

【问题讨论】:

  • 只是一个建议:如果您在派生类中覆盖虚函数,请使用override
  • getLearner() 实例化了什么?
  • 我还应该补充一点,我曾尝试将“学习者”显式转换为 NeuralNet*,但没有成功。
  • 可能性(1)getLearner 实际上没有返回指向NeuralNet 的指针。测试dynamic_cast<NeuralNet*>(learner) == nullptr。方法名称之一中的可能性 (2) 拼写错误导致派生类的方法实际上不是覆盖。
  • @ScottCrunketon 确保矩阵类型相同。确保将这两个类放在同一个文件中。还要确保您没有意外从其他 SupervisedLearner 类派生...

标签: c++ c++11 polymorphism overriding


【解决方案1】:

我发现了问题所在。问题出在两行之间的装饰器类上:

SupervisedLearner* learner = getLearner(model, r, parser.getLearnerExtra());
...
double accuracy = learner->measureAccuracy(trainFeatures, trainLabels, &stats);

所以,代码看起来像:

SupervisedLearner* learner = getLearner(model, r, parser.getLearnerExtra());
...
learner = new Normalize( learner );
...
double accuracy = learner->measureAccuracy(trainFeatures, trainLabels, &stats);

Normalize 装饰器看起来像:

class Normalize: public SupervisedLearner {
private:
    SupervisedLearner* innerLearner;
public:
    Normalize(SupervisedLearner* learner) : learner(innerLearner) {}
    ...
}

装饰器没有覆盖 SupervisedLearner 方法。感谢大家的帮助。感谢 @Casey 的 dynamic_cast(learner) == nullptr 提示。

【讨论】:

    【解决方案2】:

    尝试将关键字virtual 添加到您的子函数中,这样编译器就知道它是一个虚函数。 通过不添加虚拟,您正在实现一个全新的功能: Object = (构造函数,析构另一个度量函数,父度量函数) 当你运行代码时,编译器会决定使用哪个函数

    如果您将 virtual 添加到您的子函数,它将如下所示: Object =(构造函数、析构函数、子度量函数、父度量函数) 当你用这个运行代码时,编译器将使用子函数

    【讨论】:

    • 如果你有一个在父类中声明为虚拟的函数,它在所有子类中实际上都是虚拟的。在孩子中添加 virtual 关键字是一种很好的做法,但在这种情况下不会影响结果。
    猜你喜欢
    • 1970-01-01
    • 2011-04-17
    • 2016-02-23
    • 2017-11-18
    • 2018-06-02
    • 1970-01-01
    • 2021-02-10
    • 1970-01-01
    相关资源
    最近更新 更多