当函数返回类型是父类时,如何返回子类的对象?

时间:2017-06-23 14:26:12

标签: c++ c++11 polymorphism

我猜Java可以将子类的对象替换为父类的对象。我想用c ++做。

我正在努力做到如下。但是,我得到了“错误:返回类型'食物'是一个抽象类”错误。我该如何解决?

之前它有效:

#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;
}

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

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的智能指针作为我的笔记后发布更新。

3 个答案:

答案 0 :(得分:2)

在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的智能指针或简单的原始指针。

答案 1 :(得分:1)

您需要通过指针类型或对基类的引用返回,而不是按值返回。这是必需的,因为您的基类是一个抽象类,您无法实例化一个抽象类。那说你可以做到

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")

答案 2 :(得分:1)

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