简体   繁体   中英

Pure Virtual Function error in factory design pattern

studying for a final and decided to build a program which makes use of pure virtual functions and polymorphism. i am stuck on a really weird error maybe i am missing something.

This is the Shape abstract class

#ifndef Shape_hpp
#define Shape_hpp

#include <stdio.h>
#include <string.h>

class Shape{
    const char* name;
public:
    Shape(const char* abc);
    virtual double getPerimeter()=0;
    virtual double getArea()=0;
};

#endif /* Shape_hpp */

The Shape .cpp implementation file

#include "Shape.hpp"

Shape::Shape(const char *shape){
    name = shape;
}

The Circle Header file

#ifndef Circle_hpp
#define Circle_hpp

#include "Shape.hpp"
#include <stdio.h>

class Circle:public Shape{
    double m_radius;
public:
    Circle(double rad);
    double getRadius();            
};

#endif /* Circle_hpp */

The circle .cpp implementation file

#include "Circle.hpp"
#include "Shape.hpp"

Circle::Circle(double rad):Shape("Circle"){
    m_radius = rad;
}

double Circle::getRadius(){
    return m_radius;
}

double Circle::getPerimeter(){
    return (2 * 3.14 * m_radius);
}

double getArea(){
   return 0;
}

I declared the two pure virtual functions in the abstract "shape" class and am accessing the public of shape class in circle header file, if i declare the pure virtual functions in the circle class it will make it abstract... the error says "Out-of-line definition of 'getPerimeter' does not match any declaration in 'Circle'"

Am i missing something or am i thinking about this the wrong way..

Help would be appreciated. Thanks!

You need to declare all member functions that you define. So in class Circle you need to add:

virtual double getPerimeter();

Or better in C++11:

double getPerimeter() override;

You're defining Circle::getPerimeter() in your .cpp file but there is no member function getPerimeter() in the Circle class declaration. All pure virtual functions need to be overriden in a derived class in order for the class to become concrete. So yes, virtual double getPerimeter(); and override if you're using C++11.

Also, it's good practice to declare simple getters const .

It should be done this way.

class Shape{
    const char* name;
public:
    Shape(const char* abc);
    virtual ~Shape() {} // you should have virtual destructor here
    virtual double getPerimeter()=0;
    virtual double getArea()=0;
};
class Circle:public Shape{
    double m_radius;
public:
    Circle(double rad);
    double getRadius();
    virtual double getPerimeter(); // we need to re-declare it here
    virtual double getArea(); // we need to re-declare it here
};

Here's a suggestion. Since Shape is an abstract class, we cannot create objects of the class; so get rid of its constructor. Since we are interested in area and parameter of shapes, define the functions as virtual.

So, here is a redeclaration of Shape class.

#ifndef __SHAPE__
#define __SHAPE__
namespace shape
{
    class Shape
    {
        public:
            virtual float getArea()=0;
            virtual float getPerimeter()=0;
    };
}
#endif

Now, redeclaration of Circle class

#ifndef __CIRCLE__
#define __CIRCLE__
#include "inc/Shape.hpp"
namespace shape
{
    class Circle: public Shape
    {
        float radius;
        public:
            Circle(float=0.0);
            float getArea();
            float getPerimeter();
    };
}
#endif

Now redefining Circle class

#include "inc/Circle.hpp"
namespace shape
{
    Circle::Circle(float radius)
    {
        this->radius = radius;
    }
    float Circle::getArea()
    {
        return ((22/7) * (this->radius * this->radius));
    }
    float Circle::getPerimeter()
    {
        return (2 * (22/7) * this->radius);
    }
}

Now, in the main class

#include <iostream>
#include "inc/Circle.hpp"

int main()
{
    shape::Shape *circle = new shape::Circle(2.5);
    std::cout << "Area: " << circle->getArea() << std::endl;
    std::cout << "Perimeter: " << circle->getPerimeter() << std::endl;
    return 0;
}

You may redeclare the classes without namespaces.

The point to note is that the type of object created should be of the parent class and the object itself should be a child class.

One last thing; all pure virtual functions in the abstract must be redeclared and redefined (overridden) in the derived classes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM