C++ 为什么此代码返回-nan(ind)?c++;

C++ 为什么此代码返回-nan(ind)?c++;,c++,testing,scale,C++,Testing,Scale,我正在尝试编写一个Scaler类,它接受一个有分数的子测试 Scaler使用其子级的score类的scale方法来重新缩放其值(例如,1/1的scale 5=5/5或0/1的scale 5=0/5) 但是,每当我使用DummyTest类作为子类运行代码时,它都会返回“-nan(ind)/5,而不是5/5和我的 测试用例(“缩放测试返回1/1到5/5”) { 自动测试=标准::使_共享(分数(1,1));//总是返回1/1的测试 定标器定标器(试验,5); 检查(scaler.run()=分数(5

我正在尝试编写一个Scaler类,它接受一个有分数的子测试

Scaler使用其子级的score类的scale方法来重新缩放其值(例如,1/1的scale 5=5/5或0/1的scale 5=0/5)

但是,每当我使用DummyTest类作为子类运行代码时,它都会返回“-nan(ind)/5,而不是5/5和我的

测试用例(“缩放测试返回1/1到5/5”)
{
自动测试=标准::使_共享(分数(1,1));//总是返回1/1的测试
定标器定标器(试验,5);
检查(scaler.run()=分数(5,5));
}
这是我的代码:

class Score {
public:
    double value;
    double maximum;

    Score() : value(0), maximum(0) { }                          
    Score(double maximum) : value(0), maximum(maximum) { }      
    Score(double value, double maximum) : value(value), maximum(maximum) { }

    Score scale(double scale) const;
    bool success();
};

Score Score::scale(double scale) const {
    double a = (value / maximum) * scale;
    double b = scale;
    return Score(a , b);
}

class Test {
public:
    virtual Score run() const;
};

class DummyTest : public Test {
    Score score;

public:
    DummyTest(const Score& score) : score(score) { }

    Score run() const override {
        return score;
    }
};

class Scaler : public Test {
public:
    Test child;
    double maximum;

    Scaler(std::shared_ptr<Test> child, double maximum) : child(*child), maximum(maximum) { }

    Score run() const override;

};

Score Scaler::run() const {
    Score c = child.run().scale(maximum);
    return c;
}
班级成绩{
公众:
双重价值;
双倍最大值;
Score():值(0),最大值(0){
分数(双倍最大值):值(0),最大值(最大值){}
分数(双倍值,双倍最大值):值(值),最大值(最大值){}
得分量表(双量表)常数;
bool success();
};
分数:刻度(双刻度)常数{
双a=(值/最大值)*刻度;
双b=刻度;
返回分数(a、b);
}
课堂测试{
公众:
虚拟分数运行()常量;
};
DummyTest类:公共测试{
得分;
公众:
DummyTest(常量分数和分数):分数(分数){}
Score run()常量覆盖{
返回分数;
}
};
类定标器:公共测试{
公众:
测试儿童;
双倍最大值;
Scaler(std::shared_ptr child,双倍最大值):child(*child),max(max){
Score run()常量覆盖;
};
分数定标器::run()常量{
得分c=儿童跑步()量表(最大值);
返回c;
}

您已经成为所谓的错误的牺牲品;为了更好地说明,我将代码简化了一点(不管您是通过智能指针还是原始指针接收指针…)

具体情况是,将派生类分配给基类的实例。基类(作为值)不能保存派生类的实例,因此属于派生类的所有数据都被“切断”,或者换句话说,只有派生类的基类部分被复制到tests成员中。由于它现在是一个真正的
Test
实例,因此它将调用
Test::run()
,它只返回
Score()
,最后以0除法结束

现在,既然您已经引入了智能指针,那么可以从以下方面获益:

class Scaler
{
    std::shared_ptr<Test> child;
    Scaler(std::shared_ptr<Test> const& child, double maximum)
           // you don't need the reference counting stuff for the parameter,
           // so you can pass as reference
        : child(child) // assigning the reference to our member
                       // (now with reference count management)
        { }
};
这甚至允许在测试函数中使用更简单的代码:

DummyTest test(Score 1,1));
Scaler s(test, 5);
但是,请注意,对于原始引用,您需要确保引用的测试至少与引用的测试一样长(或者至少,只要引用测试仍在使用其引用),否则您会遇到未定义的行为。这是由上面的代码片段保证的,但是,如果您这样做:

 Scaler s(DummyTest(Score 1,1));
 s.run();

现在,在从构造函数返回后,
DummyTest
实例再次被释放,您在
s.run()
中有一个悬空引用

绝对不需要智能指针,让Scaler接受const引用,您只需使用
DummyTest测试(分数1,1));定标器(试验5)
一般来说,你不应该使用智能指针作为函数参数,除非在某些特殊情况下-查看Herb Sutter的详细信息…你没有为你的
Test
基类提供虚拟析构函数-你将无法通过指向
Test
的指针删除派生
Test
对象(
Test*t=new-DerivedTest();
)这样。虽然您还没有这样做,但如果您有虚拟函数,请养成始终提供虚拟析构函数的好习惯。CHECK macro做什么?并且您没有在此处定义==运算符…使用常量引用而不是智能指针似乎可以解决问题,谢谢您!acacagua!@J.S,但前提是您将
子对象>成员一个引用,否则你会再次得到对象切片,请看我的答案。。。
class Scaler
{
    Test& child;
    //  ^ (!)
    Scaler(Test& child, double maximum)
        : child(child), maximum(maximum)
    { }
};
DummyTest test(Score 1,1));
Scaler s(test, 5);
 Scaler s(DummyTest(Score 1,1));
 s.run();