如何在C ++中使用接口

时间:2019-01-06 10:33:54

标签: c++

我正在学习C ++,无法理解接口的工作方式。我已经建立了一个无效的小示例,并且我不明白自己做错了什么。

我已经阅读了this答案,这有助于我声明接口,但是(即使我仍然不完全理解该声明),现在我的关注点更多是关于用法。我也已经读过this答案,但是仍然不能使用我的界面,请参见以下示例:

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
}

构建此文件时,我得到:

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

第二个错误使我感到困扰,因为在接口getArea()中未实现Shape正是我所期望的。第一个和第三个错误,我一点也不明白。我试图将主体更改为:

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

但是从向量中抱怨allocating an object of abstract class type 'Shape'的错误

我可能在这里错过了一些重要的事情,但是我有点卡住了...

EDIT:如注释中所建议,我在构造函数中使用了成员初始化列表,而不是向主体中的成员分配值。

1 个答案:

答案 0 :(得分:7)

在C ++中,继承仅在具有指向对象的指针或引用时起作用。您不能拥有vector<Shape>,因为Shape不存在。我猜您是来自对象变量始终是引用(例如Java)的背景。

所以这是有效的

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

但是原始指针不是好的C ++。因此,最好使用某种智能指针

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

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