C ++继承:使用派生类的实例调用基类的虚函数

时间:2014-03-28 21:54:57

标签: c++ oop inheritance

我试图了解虚拟函数和C ++中的继承。在下面的示例代码中,我有两个类AreaCube(基类)和SideAreaRatio(派生类)。我试图在派生类中的另一个函数“ ratio ”中调用基类中的虚函数“ area ”。我正在尝试使用基类的实例来实现这一点。但由于某些我不熟悉的原因,我看到生成了奇怪的答案。请在这里告诉我发生了什么!

#include<iostream>
using namespace std;

class AreaCube {
public:
    int side;
    AreaCube() {};

    AreaCube(int s) {
        side = s;
    }
    virtual ~AreaCube() {};

    virtual int area() {
        cout<< "calling.. " << endl;
        int area = side*side*side;
        return area;
    }
};

class SideAreaRatio:public AreaCube {
public:
    SideAreaRatio(int s) {
        side = s;
    };

    ~SideAreaRatio() {};

    float ratio() {
        AreaCube a;
        int area = a.area();
        cout<< area << endl;
        return (side/area);
    }
};

int main() {
    AreaCube* ac = new AreaCube(2);
    cout<< ac->area() << endl;
    SideAreaRatio* sar = new SideAreaRatio(4);
    cout<< sar->ratio() << endl;
}

预期输出:

calling.. 
8
calling.. 
8
0.3333

生成输出:

calling.. 
8
calling.. 
-1265467392
0

5 个答案:

答案 0 :(得分:2)

您使用默认构造函数创建的a的新实例AreaCube,该实例未在实例side上设置a的值。此内存不能保证保留任何特定值,当您调用a.area()时,结果将是未定义的。

有一个简单的解决方法:将AreaCube a;替换为AreaCube a(side);,看看你是否得到了正确的行为。或者,您可以避免完全实例化AreaCube的新实例,只需直接调用基类方法:int area = AreaCube::area()。请注意,您不需要在此处传递side,因为基类方法对当前对象的(this)状态进行操作。

此外,另一个阻止此工作的问题是:当您划分两个int变量时,它会将结果截断为int。你需要让它来执行浮点除法:用return (side/area);替换return (1.0f * size / area);,一切都应该没问题。

答案 1 :(得分:2)

它没有工作,因为你实际上没有用任何值构造AreaCube对象,所以当它计算区域时它会给你垃圾(因为side变量有没有值,如调用默认构造函数所示。)

认为你想要做的是:

#include<iostream>
using namespace std;

class AreaCube {
public:
    int side;
    AreaCube() {};

    AreaCube(int s) {
        side = s;
    }
    virtual ~AreaCube() {};

    virtual int area() {
        cout<< "calling.. " << endl;
        int area = side*side*side;
        return area;
    }
};

class SideAreaRatio:public AreaCube {
public:
    SideAreaRatio(int s) {
        side = s;
    };

    ~SideAreaRatio() {};

    float ratio() {
        int area = area();
        cout<< area << endl;
        return (side/area);
    }
};

int main() {
    AreaCube* ac = new AreaCube(2);
    cout<< ac->area() << endl;
    SideAreaRatio* sar = new SideAreaRatio(4);
    cout<< sar->ratio() << endl;
}

您不需要在派生类中实例化AreaCube,因为您需要的所有内容都已存在。只需调用area()方法。

从基类继承时,保留所有成员变量和成员函数,因此除了派生类之外,不需要实例化任何内容。因此,在这种情况下,SideAreaRatio既有side变量又有area()方法

值得一提的是,你并没有真正使用virtual方法做任何事情。

答案 2 :(得分:1)

SideAreaRatio类中,在调用AreaCube而不初始化{{1}时,使用默认构造函数(AreaCube())创建类型为ratio的新对象该类的成员字段。接下来,继续对仍未定义的side值进行计算。

答案 3 :(得分:1)

float ratio()更改为

float ratio() {
    int area = area();
    cout<< area << endl;
    return (side/area);
}

由于SideAreaRatio 是-a AreaCube,因此可以直接使用区域功能。

答案 4 :(得分:0)

这里

float ratio() {
    AreaCube a;
    int area = a.area();
    cout<< area << endl;
    return (side/area);
}

创建一个使用默认构造函数启动的对象。但是,AreaCube的默认构造函数不执行任何操作。因此,如果您真的想要创建一个新对象,请使用

AreaCube a(side);

代替。

或者你可以打电话

area() 

直接不创建AreaCube的新对象,即

 float ratio() {

    return (side/area());
}

你打电话的原因

area() 

直接就是这个方法是在基类中定义的。在这种情况下,即使它没有被定义为虚拟,您仍然可以使用它。你可以尝试看看结果是一样的。

基本上你的代码不是虚函数的正确实现。