【问题标题】:How to return child class's object when function return type is parent class?当函数返回类型为父类时如何返回子类的对象?
【发布时间】:2017-06-23 14:26:12
【问题描述】:

我猜想Java 可以用子类的对象代替父类的对象。我想用 C++ 来做。

我正在尝试按照以下方式进行操作。但是,我收到“错误:返回类型 'Food' 是一个抽象类”错误。我该如何解决?

使用之前

#include <iostream>

using namespace std;

class Food {
    public:
        virtual void SetPrice(int myprice) = 0;
        int GetPrice() {
            return price;
        }
    protected:
        int price;
};

class Fruit : public Food {
    public:
        void SetPrice(int myprice) {
            price = myprice - 20;
        }
};

class Fish : public Food {
    public:
        void SetPrice(int myprice) {
            price = myprice / 2;
        }
};

int main(int argc, char* argv[])
{
    Food *pFood;
    Fruit myFruit;
    Fish myFish;

    if (strcmp(argv[1], "fruit") == 0) {
        pFood = &myFruit;
    } else {
        pFood = &myFish;
    }

    pFood->SetPrice(100);
    cout << pFood->GetPrice() << endl;

    return 0;
}

After 类定义被省略。它不起作用:

Food getFoodObject(string type)
{
    if (strcmp(type, "fruit") == 0) {
        Fruit myFruit;
        return &myFruit; // I don't want to write 2 lines. I want to return the above line. This is my another question...
    }

    Fish myFish;
    return &myFish;
}

int main(int argc, char* argv[])
{
    Food *pFood;

    pFood = getFoodObject(argv[1])

    pFood->SetPrice(100);
    cout << pFood->GetPrice() << endl;

    return 0;
}

更新 1

多亏了很多建议,我的问题得到了解决。我需要使用 c++11,所以我使用 unique_ptr 而不是 make_unique。

std::unique_ptr<Food> getFoodObject(string type)
{
    if (type == "fruit") {
        return std::unique_ptr<Fruit>(new Fruit);
    }   
   return std::unique_ptr<Fish>(new Fish);
}

int main(int argc, char* argv[])
{
    std::unique_ptr<Food> pFood = getFoodObject(argv[1]);

    pFood->SetPrice(100);
    cout << pFood->GetPrice() << endl;

    return 0;
}

@dlasalle 提到了 Boost 库。在我可以使用 Boost 的智能指针作为我的笔记之后,我会发布更新。

【问题讨论】:

  • 那么您有 2 个问题还是 1 个问题? :P
  • pFood 是一个指针。 getFoodObject 返回一个对象,而不是指针。在 Java 中,几乎所有东西都是隐式指针。所以你也应该使用指针来实现你想要的
  • 发布真实代码! strcmp(type, "fruit") 不会与 string type 一起编译。
  • @manni66 该错误低于关于返回类型抽象性的错误。 OP 按降序修复错误似乎是合理的。

标签: c++ c++11 polymorphism


【解决方案1】:

在 Java 中,您总是返回一个引用(一个美化的指针),但在 C++ 中,您可以选择按值、按引用或按指针返回对象。 C++ 中的多态性只能通过引用和指针实现。

通过按值返回父类,您最终会得到object slicing,但也会得到一个无效的抽象类实例(因此编译器错误)。

你想做这样的事情:

#include <memory>

std::unique_ptr<Food> getFoodObject(string type)
{
    std::unique_ptr<Food> ptr;
    if (type.compare("fruit") == 0) {
        ptr.reset(new Fruit());
    } else {
        ptr.reset(new Fish());
    }

    return ptr;
}

如果您不使用 c++11,则需要使用 boost 的智能指针或简单的原始指针。

【讨论】:

  • 感谢您的解释。我正在了解 C++ 中的多态性。
【解决方案2】:

您需要按指针类型或对基类的引用返回,而不是按值返回。这是必需的,因为您的基类是抽象类并且您不能实例化抽象类。那就是说你可以这样做

Food* getFoodObject(string type)
{
    if (strcmp(type, "fruit") == 0) {
        Fruit myFruit;
        return &myFruit; // I don't want to write 2 lines. I want to return the above line. This is my another question...
    }

    Fish myFish;
    return &myFish;
}

因为你返回一个指向函数本地对象的指针,一旦函数退出,对象就会被销毁,留下一个悬空指针。我们可以做的是将代码更改为使用std::unique_ptr(使用智能指针为我们管理内存),然后你可以有类似的东西

std::unique_ptr<Food> getFoodObject(string type)
{
    if (type == "fruit") {
        return std::unique_ptr<Fruit>(new Fruit);
        // or in C++14 return std::make_unique<Fruit>();
    }
    return std::unique_ptr<Fish>(new Fish);
    // or in C++14 return std::make_unique<Fish>();
}

你会像这样调用函数

int main(int argc, char* argv[])
{
    std::unique_ptr<Food> pFood = getFoodObject(argv[1])

    pFood->SetPrice(100);
    cout << pFood->GetPrice() << endl;

    return 0;
}

还要注意if (strcmp(type, "fruit") == 0) 无效。 strcmp 处理 c 字符串,而不是 std::string。要比较std::string,您可以使用==,例如if (type == "fruit")

【讨论】:

  • 你错过了几个returns。
  • @themiurge 谢谢。意外覆盖他们
  • 它需要 C++14 ) 显然他不明白 C++ 中的内存是如何工作的,因为他返回堆栈分配对象的指针。
  • 非常感谢。我必须使用 c++11。我正在调查它。我会尽快发布我的结果。
  • @zono 要使其在 C++11 下工作,您必须将 std::make_unique&lt;Fish&gt; 替换为 std::unique_prt&lt;Fish&gt;... 之类的东西
【解决方案3】:

您可以在 C++ 中使用指针。抽象类不能被实例化,因此不能将抽象基类用作实例。您可以创建父具体类,然后使用为它设置基类的指针。

【讨论】:

    猜你喜欢
    • 2018-03-11
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    相关资源
    最近更新 更多