【问题标题】:How to use interfaces in c++如何在 C++ 中使用接口
【发布时间】:2019-01-06 10:33:54
【问题描述】:

我正在学习 C++,我无法理解接口的工作原理。我设置了一个不起作用的小例子,我不明白我做错了什么。

我已经阅读了this 的答案,它帮助我声明了接口,但是(即使我仍然不完全理解声明)我现在更关心的是用法。我也读过this 的答案,但我仍然无法使用我的界面,请参阅此示例:

形状.h

#ifndef SHAPE_H
#define SHAPE_H

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

#endif // SHAPE_H

矩形.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

矩形.cpp

#include "rectangle.h"

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

奇怪的.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

奇怪的.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);
                  ^

第二个错误困扰着我,因为在Shape 类中没有实现getArea() 正是我对接口的期望。第一个和第三个错误,我完全不明白。我试图将主要更改为:

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

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

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

编辑:正如 cmets 中所建议的,我在构造函数中使用了成员初始化列表,而不是为主体中的成员赋值。

【问题讨论】:

  • 查找std::vector 元素的要求,使用std::vector&lt;std::unique_ptr&lt;Shape&gt;&gt; 可能没问题。
  • 不是重点,但对于构​​造函数,您应该使用member initialization lists,如Rectangle::Rectangle(int w, int h) : width{w}, height{h} {},而不是像那样分配体内的成员。

标签: c++


【解决方案1】:

在 C++ 中,继承仅在您拥有指向对象的指针或引用时才有效。您不能拥有vector&lt;Shape&gt;,因为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));

【讨论】:

  • 这并不是说继承不起作用,它是 运行时多态性,它仅在通过对基类的指针/引用访问对象时才有用,作为 值语义 不允许将派生对象复制到基础实例中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多