【问题标题】:Why is class abstract although it shouldn't be?为什么类是抽象的,虽然它不应该是?
【发布时间】:2022-01-20 16:25:57
【问题描述】:

我已经查看这段代码几个小时了,但我找不到为什么我不能实例化类。所以我有接口:

class ICloneable {
    public:
    virtual ICloneable* clone() const = 0;
    virtual ~ICloneable() = 0 {}
};


class IPrintable
{
    protected:
        virtual void print(std::ostream&) const = 0;
    public:
        virtual ~IPrintable() = 0;
        friend std::ostream& operator<<(std::ostream, const IPrintable&);
};
std::ostream& operator<<(std::ostream os, const IPrintable& other) {
    other.print(os);
    return os;
}


class IComparable {
    protected:
        virtual bool is_greater(const IComparable& other) const = 0;
        virtual bool is_equal(const IComparable& other) const = 0;
    public:
        virtual ~IComparable() = 0;
        virtual bool operator>(const IComparable& other) const {
            return is_greater(other);
        }
        virtual bool operator<(const IComparable& other) const {
            return !(is_greater(other) || is_equal(other));
        }
        virtual bool operator==(const IComparable& other) const {
            return is_equal(other);
        }
        virtual bool operator!=(const IComparable& other) const {
            return !(is_equal(other));
        }
};

我有两个类继承了这些接口:

class I2DShape : public IComparable, public IPrintable {
    public:
        virtual void print(std::ostream& os) const override final {
            os << "Circumference: " << this->circumference();
        }
        virtual bool is_greater(const I2DShape& other) const final {
            return this->circumference() > other.circumference();
        }
        virtual bool is_equal(const I2DShape& other) const final {
            return this->circumference() == other.circumference();
        }

        virtual double circumference() const = 0;
        virtual ~I2DShape();
};


class IPositionable : public IPrintable, public IComparable {
    public:
        virtual void print(std::ostream& os) const override final {
            
        }

        virtual bool is_greater(const IPositionable& other) const final {
            distance_from_origin() > other.distance_from_origin();
        }
        virtual bool is_equal(const IPositionable& other) const final {
            distance_from_origin() == other.distance_from_origin();
        }
        
        virtual double distance_from_origin() const {
            return sqrt(pow(center().get_x(), 2) + pow(center().get_y(), 2));
        }
        virtual Point center() const = 0;
        virtual ~IPositionable();
};

最后这两个类被一个代表形状的类继承:

class Shape2D : public IPositionable, public I2DShape, public ICloneable {
    protected:
        int num_of_points;
        Point* points;
    public:
        Shape2D() : num_of_points(0), points(nullptr) {}
        Shape2D(int num) : num_of_points(num), points(new Point[num]) {}
        Shape2D(const Shape2D& other) : num_of_points(other.num_of_points) {
            points = new Point[num_of_points];
            for (int i = 0; i < num_of_points; i++) {
                points[i] = other.points[i];
            }
        }
        Shape2D& operator=(const I2DShape& other) {
            
        }
        virtual Shape2D* clone() const override = 0;
        virtual ~Shape2D() {
            if(points)
                delete[] points;
        }
};

当我从 Shape2D 派生 Square 并创建克隆函数时,我收到错误,它是抽象类:

class Square : public Shape2D {
    private:
        double side;
    public:
        Square() {}
        Square(double s, Point center) : side(s), Shape2D(1) { points[0] = center;}
        
        virtual Point center() const override{
            return points[0];
        }
        virtual double circumference() const override {
            return 4 * side;
        }
        virtual Square* clone() const override final {
            return new Square(*this); //error on this line
        }
};

错误:不允许抽象类类型“Square”的对象

【问题讨论】:

  • virtual ~ICloneable() = 0 {} 不是有效的 C++。您的代码也无法编译,因为它使用了未声明的类型,例如 Point
  • 要使其有效,必须将其声明为... = 0;,然后在类主体之外定义。
  • Clang gave me 作为非覆盖虚拟方法的列表。 virtual bool is_greater(const IPositionable&amp; other)等不覆盖基类方法,因为参数类型不同。如果您使用override,编译器不会告诉您这一点。以后,请以minimal reproducible example 的形式附上代码——我们可以直接粘贴到编译器中而不会添加缺少的头文件或类的单件。
  • Shape2D 继承了 is_greater 等的多个定义。人。来自IPositionableI2DShape。您期望/希望它使用哪个?
  • @Brian 我没有包括Point,因为它是普通类。我修复了virtual ~ICloneable() = 0 {},但问题仍然存在。

标签: c++ inheritance abstract-class multiple-inheritance


【解决方案1】:

错误如 cmets 中的@HolyBlackCat 所述,具有函数is_greateris_equal,因为它们在被覆盖时具有不同的参数。对此的简单解决方法是从IComparable 中的这两个函数中删除= 0,这样它们就不是纯的了。

【讨论】:

  • 但是......那么它们将不会被覆盖。
  • 怎么回事?我的意思是它们仍然是虚拟的。
  • 因为参数类型不同。当您删除 =0 时,这不会改变。
  • 我不知道现在该做什么。我发现了这篇文章:(stackoverflow.com/a/1184475/14340115) 但它在多态方面似乎是错误的。我看到了你关于概念的回答,但作业要我用接口来做。
  • Uhh... 你可以用IComparable 作为参数覆盖is_greater,然后将dynamic_cast 改成正确的类型。很傻,但应该可以。
【解决方案2】:

由于您在接口中使用= 0 声明了析构函数,因此您正在强制在可以实例化的子类中显式实现它。

有两种方法可以修复它。

  • 使用{}= default 以标准方式使用默认析构函数(无= 0)创建接口类。
  • Square 添加显式析构函数

请注意,带有实现的纯虚拟析构函数是treated by gcc and clang as an error

相关的 SO 问题:

【讨论】:

  • 感谢您的回复。我为Square 添加了显式析构函数,但问题仍然存在。正如 @HolyBlackCat 在 cmets 中所述,问题可能出在函数 is_greateris_equal 上,因为它们具有不同的参数,但我不知道如何解决。
  • @qu4lizz 解决is_greater()is_equal() 问题的方法是让Shape2D 显式覆盖它们(即在类定义中使用与它们在类定义中相同的参数声明它们)基类,并定义[即实现]它们)。但这并不能解决 Brian 指出的问题 - ICloneable 的析构函数的语法无效,您还需要修复它。
  • 就像我写的:如果基类具有= 0 的虚函数,那么子类必须重写——它具有给定方法的显式实现。
猜你喜欢
  • 2013-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-22
相关资源
最近更新 更多