Home > other >  Why is class abstract although it shouldn't be?
Why is class abstract although it shouldn't be?

Time:12-18

I've been looking at this code for few hours and I can't find why I can't instantiate class. So I have interfaces:

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));
        }
};

And I have two classes that inherit these interfaces:

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();
};

And in the final these two classes are inherited by one which represents shape:

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;
        }
};

When I derive Square from Shape2D and make function for cloning, I get error that it's abstract class:

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
        }
};

Error: object of abstract class type "Square" is not allowed

CodePudding user response:

Since in interfaces you declared destructors with = 0 you are forcing explicit implementation of it in sub-classes which can be instantiated.

There are two ways to fix it.

  • Make interface classes in standard way with default destructors (no = 0), using {} or = default.
  • Add explicit destructor for Square

Note that pure virtual destructor with implementation is treated by gcc and clang as an error.

Related SO questions:

CodePudding user response:

The error was as @HolyBlackCat stated in the comments, with function is_greater and is_equal because they have different parameters when overriden. Simple fix to this was to remove = 0 from those two functions in IComparable so they weren't pure.

  • Related