永远不会调用虚函数

时间:2015-03-12 11:55:48

标签: c++

我试图在同一基类的不同子类之间实现比较。如果两个实例具有不同的子类,则比较应返回false,如果它们属于同一子类,则返回实际比较结果。

检查函数main中的最后一行:虽然我已将equalTo声明为virtual,但只调用基类的equalTo方法。我的错是什么?

提前致谢。

#include <iostream>
#include <fstream>
#include <cmath>
#include <limits>
#include <sstream>
#include <stdexcept>
#include <algorithm>

using namespace std;

bool fileInput = false, fileOutput = false;

class Point
{
public:
    double x,y;
    Point(){};
    Point(double x1, double y1) {
        x=x1;
        y=y1;
    }
    bool operator==(Point other) const
    {
        return (abs(x - other.x) < numeric_limits<double>::epsilon()) and (abs(y - other.y) < numeric_limits<double>::epsilon());
    }
};

class Shape
{
protected:
    virtual double area() const
    {
        return 0;
    }
    virtual void print(std::ostream& os) const {}
    virtual void read(std::istream& is) {}
public:
    bool compare(Shape* other) {
        return area() < other->area();
    }
    virtual bool equalTo(Shape other) const {
        cout << "original";
        return false;
    }
    friend std::ostream& operator<<(std::ostream &strm, const Shape &t)
    {
        t.print(strm);
        return strm;
    }
    friend std::istream& operator>>(std::istream &strm, Shape &t)
    {
        t.read(strm);
        return strm;
    }
};

class Circle : public Shape
{
    Point c;
    double r;
    double area() const
    {
        return M_PI * r * r;
    }
    void print(std::ostream &strm) const
    {
        strm << "Circle. Center coordinates: (" << c.x << "," << c.y << "). Radius: " << r << ". Area: " << area();
    }
    void read(std::istream &strm)
    {
        if (!fileInput) cout << "Enter Circle\nCenter: ";
        strm >> c.x >> c.y;
        if (!fileInput) cout << "Radius: ";
        strm >> r;
        if (r<0)
            throw std::invalid_argument( "The radius cannot be negative." );
    }
public:
    Circle() {}
    Circle(Point x, double y)
    {
        c = x;
        r = y;
    }
    bool equalTo(Shape other1) const
    {
        Circle* other = dynamic_cast<Circle*>(&other1);
        if (other == 0) return false;
        return (c == other->c) and (abs(r - other->r)<numeric_limits<double>::epsilon());
    }
};

class Hexagon : public Shape
{
    Point c;
    double r;
    double area() const
    {
        return 1.5 * sqrt(3) * r * r;
    }
    void print(std::ostream &strm) const
    {
        strm << "Hexagon. Center coordinates: (" << c.x << "," << c.y << "). Circumcircle radius: " << r << ". Area: " << area();
    }
    void read(std::istream &strm)
    {
        if (!fileInput) cout << "Enter Hexagon\nCenter: ";
        strm >> c.x >> c.y;
        if (!fileInput) cout << "Circumcircle radius: ";
        strm >> r;
        if (r<0)
            throw std::invalid_argument( "The circumcircle radius cannot be negative." );
    }
public:
    Hexagon() {}
    Hexagon(Point x, double y)
    {
        c = x;
        r = y;
    }
    bool equalTo(Shape other1) const
    {
        Hexagon* other = dynamic_cast<Hexagon*>(&other1);
        if (other == 0) return false;
        return (c == other->c) and (abs(r - other->r)<numeric_limits<double>::epsilon());
    }
};

int main()
{
    Shape c1 = Circle(Point(0,0), 3);
    Shape c2 = Circle(Point(0,0), 3);
    Shape c3 = Hexagon(Point(0,0), 3);
    cout << "circles: " << c1.equalTo(c2) << endl << "diff: " << c1.equalTo(c3) << endl;
}

2 个答案:

答案 0 :(得分:3)

这是切片,当您将对象分配给类型为Shape的对象时 - 对象被切成Shape。使用指针,或者可以是引用。

Circle p1(Point(0, 0), 3);
Circle p2(Point(0, 0), 3);
Hexagon h1(Point(0, 0), 3);
Shape& c1 = p1;
Shape& c2 = p2;
Shape& c3 = h1;

答案 1 :(得分:1)

当您从派生类中复制构造Shape时,该对象将切片,以便仅保留它的Shape部分。然后当你调用equalTo时,该函数是静态绑定的。

要调用衍生版本,请将c1和朋友加入Shape&