aTom
aTom

Reputation: 546

How to use interfaces in c++

I'm learning C++, I have trouble understanding how interfaces work. I've set up a small example which doesn't work, and I don't understand what I've done wrong.

I've read this answer, which helped me declaring the interface, but (even if I still don't understand fully the declaration) my concern right now is more about the usage. I've read this answer too, but still, I can't use my interface, see this example :

shape.h

#ifndef SHAPE_H
#define SHAPE_H

class Shape
{
public:
    virtual ~Shape(){}
    virtual int getArea() = 0;
};

#endif // SHAPE_H

rectangle.h

#ifndef RECTANGLE_H
#define RECTANGLE_H

#include "shape.h"

class Rectangle : public Shape
{
public:
    Rectangle(){}
    Rectangle(int w, int h) : width{w}, height{h} {}
    virtual int getArea();
private:
    int width = 0;
    int height = 0;
};

#endif // RECTANGLE_H

rectangle.cpp

#include "rectangle.h"

int Rectangle::getArea()
{
    return width * height;
}

weird.h

#ifndef WEIRD_H
#define WEIRD_H

#include "shape.h"

class Weird : public Shape
{
public:
    Weird(){}
    Weird(int a) : area(a){}
    virtual int getArea();
private:
    int area = 0;
};

#endif // WEIRD_H

weird.cpp

#include "weird.h"

int Weird::getArea()
{
    return area;
}

main.cpp

#include <cstdio>
#include <vector>

#include "shape.h"
#include "weird.h"
#include "rectangle.h"

int main(void)
{
    std::vector<Shape> shapes;
    Shape shapeA = Weird(12);
    Shape shapeB = Rectangle(2, 3);

    shapes.push_back(shapeA);
    shapes.push_back(shapeB);

    int total = 0;
    for(auto&& s : shapes)
    {
       total += s.getArea();
    }

   printf("%d\n", total); //Would expect 18
}

When I build this, I get :

main.cpp:11:9: error: variable type 'Shape' is an abstract class
            Shape shapeA = Weird(12);
                  ^
./shape.h:8:18: note: unimplemented pure virtual method 'getArea' in 'Shape'
        virtual int getArea() = 0;
                    ^
main.cpp:12:9: error: variable type 'Shape' is an abstract class
            Shape shapeB = Rectangle(2, 3);
                  ^

The second error bothers me, because not implementing getArea() in the Shape class is precisely what I'm expecting from an interface. The first and third errors, I don't understand at all. I tried to change the main to :

Weird shapeA = Weird(12);
Rectangle shapeB = Rectangle(2, 3);

But got errors from the vector complaining about allocating an object of abstract class type 'Shape'

I'm probably missing a few important things here, but I'm a bit stuck...

EDIT : As suggested in comments, I used member initialization lists in constructors instead of assigning values to members in the body.

Upvotes: 0

Views: 114

Answers (1)

john
john

Reputation: 87959

In C++ inheritance only works when you have pointers or references to an object. You cannot have a vector<Shape> because Shape can't exist. I'm guessing you come from a background where object variables are always references (like Java).

So this is valid

std::vector<Shape*> shapes;
shapes.push_back(new Rectangle(2, 3));

but raw pointers are not good C++. So some sort of smart pointer is preferable

std::vector<std::shared_ptr<Shape>> shapes;
shapes.push_back(std::make_shared<Rectangle>(2, 3));

or

std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Rectangle>(2, 3));

Upvotes: 7

Related Questions