为什么调用abstractclass时不能使用继承的class?

Why can't I use the inherited class when I called abstract class?

问题:

我的代码是关于使用抽象 class Shape 并创建 3 个形状 Rectangle, Circle 三角形 。我在 ShapeFactory class 中使用了工厂和单例设计模式。当我读取文件时,我调用了方法 getInstance() 并指向 createShape 方法。之后,我指向派生的 class 并调用 setter 来设置一些变量。问题是据说我的摘要 class 没有任何 setter 成员。

尝试次数:

我已经尝试创建所有 setter 到 Shape class 并且它有效但它违反了面向对象的编程规则所以我是尝试做其他方式。我也尝试过搜索错误,但它不符合我的需求。

错误:

oop3.cpp: In member function 'void ShapeFileIO::readFile(std::__cxx11::string, std::vector<std::shared_ptr<Shape> >&)':
oop3.cpp:259:28: error: 'using element_type = class Shape' {aka 'class Shape'} has no member named 'setWidth'; did you mean '_width'?
                 rectangle->setWidth(stod(width));
                            ^~~~~~~~
                            _width
oop3.cpp:260:28: error: 'using element_type = class Shape' {aka 'class Shape'} has no member named 'setHeight'; did you mean '_height'?
                 rectangle->setHeight(stod(height));
                            ^~~~~~~~~
                            _height
oop3.cpp:270:25: error: 'using element_type = class Shape' {aka 'class Shape'} has no member named 'setRadius'; did you mean '_radius'?
                 circle->setRadius(stod(radius));
                         ^~~~~~~~~
                         _radius
oop3.cpp:284:27: error: 'using element_type = class Shape' {aka 'class Shape'} has no member named 'setSide1'; did you mean '_side1'?
                 triangle->setSide1(stod(side1));
                           ^~~~~~~~
                           _side1
oop3.cpp:285:27: error: 'using element_type = class Shape' {aka 'class Shape'} has no member named 'setSide2'; did you mean '_side2'?
                 triangle->setSide2(stod(side2));
                           ^~~~~~~~
                           _side2
oop3.cpp:286:27: error: 'using element_type = class Shape' {aka 'class Shape'} has no member named 'setSide3'; did you mean '_side3'?
                 triangle->setSide3(stod(side3));
                           ^~~~~~~~
                           _side3

我的代码:

这是我的错误代码:

auto rectangle = ShapeFactory::getInstance()->createShape("Rectangle");
                rectangle->setWidth(stod(width));
                rectangle->setHeight(stod(height));

auto circle = ShapeFactory::getInstance()->createShape("Circle");
                circle->setRadius(stod(radius));

auto triangle = ShapeFactory::getInstance()->createShape("Triangle");
                triangle->setSide1(stod(side1));
                triangle->setSide2(stod(side2));
                triangle->setSide3(stod(side3));

这是我的工厂class:

class ShapeFactory {
public:
    map<string, shared_ptr<Shape>> _prototypes;
private:
    inline static shared_ptr<ShapeFactory> _instance = nullptr;
    ShapeFactory() {
        auto rec = make_shared<Rectangle>();
        auto cir = make_shared<Circle>();
        auto tri = make_shared<Triangle>();

        _prototypes.insert({"Rectangle", rec});
        _prototypes.insert({"Circle", cir});
        _prototypes.insert({"Triangle", tri});
    }
public:
    static shared_ptr<ShapeFactory> getInstance() {
        if (_instance == nullptr) {
            auto temp = new ShapeFactory();
            _instance = shared_ptr<ShapeFactory>(temp);
        }
        return _instance;
    }

    shared_ptr<Shape> createShape(string shape) {
        auto it = _prototypes[shape];
        auto result = it->clone();
        return result;
    }
};

这是我的摘要class:

class Shape {
protected:
    string _shape;

public:
    Shape() { _shape = ""; }
    Shape(string shape) { _shape = shape; }
    virtual ~Shape() {}

public:
    void setShape(string shape) { _shape = shape; }
    virtual string magicWord() = 0;
    virtual shared_ptr<Shape> clone() = 0;
};

这是我的 ShapeFileIO class:

class ShapeFileIO {
public:
    void readFile(string fileName, vector<shared_ptr<Shape>>& shapes) {
        ifstream inFile;
        inFile.open(fileName);
        
        if (!inFile) {
            cout << "Unable to open file";
            exit(1);
        }
        string line, width, height, radius, side1, side2, side3;
        while (!inFile.eof()) {          
            getline(inFile, line);
            stringstream ss(line);
            getline(ss, width, '=');
            getline(ss, width, ',');
            getline(ss, height, '=');
            getline(ss, height);
            if (line.find("Rectangle") != string::npos) {
                auto rectangle = ShapeFactory::getInstance()->createShape("Rectangle");
                rectangle->setWidth(stod(width));
                rectangle->setHeight(stod(height));
                shapes.push_back(rectangle);
            }

            getline(inFile, line);
            stringstream ss2(line);
            getline(ss2, radius, '=');
            getline(ss2, radius);
            if (line.find("Circle") != string::npos) {
                auto circle = ShapeFactory::getInstance()->createShape("Circle");
                circle->setRadius(stod(radius));
                shapes.push_back(circle);
            }

            getline(inFile, line);
            stringstream ss3(line);        
            getline(ss3, side1, '=');
            getline(ss3, side1, ',');
            getline(ss3, side2, '=');
            getline(ss3, side2, ',');
            getline(ss3, side3, '=');
            getline(ss3, side3);
            if (line.find("Triangle") != string::npos) {
                auto triangle = ShapeFactory::getInstance()->createShape("Triangle");
                triangle->setSide1(stod(side1));
                triangle->setSide2(stod(side2));
                triangle->setSide3(stod(side3));
                shapes.push_back(triangle);
            }
        }
        cout << "File read successfully" << endl << endl;
        inFile.close();
    }
};

你的问题很容易解释,但不太容易改正。 看这一行:

auto rectangle = ShapeFactory::getInstance()->createShape("Rectangle");

我们这里有这个 auto 本应让生活更轻松,但有时它隐藏了真正的问题。即:这里 rectangle 的类型是什么?为了解决这个问题,让我们看一下 createShape:

的声明
shared_ptr<Shape> ShapeFactory::createShape(string shape); 

所以,这个函数returnsshared_ptr<Shape>。因此,您的 rectangle 也是 shared_ptr<Shape> 类型,并且在此表达式中

rectangle->setWidth(stod(width));

您告诉编译器访问 class Shape 的成员 setWidth。编译器不得不抗议并拒绝这样做,因为 Shape 是一个基础 class,没有名为 setWidth.

的方法

如何解决这个问题是另一回事。最简单的方法是对 createShape

返回的指针使用某种形式的动态转换
auto base_ptr = ShapeFactory::getInstance()->createShape("Rectangle");
auto rectangle = std::dynamic_pointer_cast<Rectangle> (base_ptr); 

它的一个问题是它很丑陋,并且存在您需要在程序的其他几个部分求助于动态转换的危险。那将是奇怪和不受欢迎的。我不使用工厂等,你需要自己找到适合你需求的解决方案。

另请参阅:

PS。下次当你在 SO 上提问时,请尝试提供 Minimal, reproducible example - 你会在发布问题几分钟后得到清晰、准确的答案。