【问题标题】:What is the correct way to have a member function return type be a superclass of the actual object you want to return?让成员函数返回类型成为您要返回的实际对象的超类的正确方法是什么?
【发布时间】:2019-12-20 15:26:51
【问题描述】:

问题

让成员函数返回类型成为您想要返回的实际对象的超类的正确方法是什么?

问题

Clang tidy 警告我返回 subClassAsubClassB 会丢弃我对 myMethod 的覆盖。我也没有得到任何输出——大概是因为我不小心丢弃了被覆盖的myMethod

代码

#include <iostream>

using namespace std;

class SuperClass {
public :
    SuperClass() {
        cout << "I'm the superclass" << endl;
    };

    virtual std::string myMethod();
};

class SubClassA : public SuperClass {
public:
    SubClassA() : SuperClass() {
        cout << "I'm subclass A" << endl;
    }

    std::string myMethod() override {
        return "A";
    }
};

class SubClassB : public SuperClass {
public:
    SubClassB() : SuperClass() {
        cout << "I'm subclass B" << endl;
    }

    std::string myMethod() override {
        return "B";
    }
};

class Client {
private:
    std::string which;

    SuperClass letterFactory(){
        if (which == "A") {
            SubClassA subClassA;
            return subClassA;
        } else if (which == "B") {
            SubClassB subClassB;
            return subClassB;
        } else {
            throw std::invalid_argument("Bad");
        }
    }

public:
    explicit Client(std::string &which) : which(which) {
        letterFactory();
    };
};

int main() {
    Client client();
    return 0;
};

【问题讨论】:

  • 您的Client 构造函数实际上是在创建然后丢弃一个SuperClass 实例,这实际上是由于您按值返回而遭受切片。
  • 您希望调用letterFactory 完成什么?
  • 请考虑以更清晰的方式形成问题。
  • @AndyG 这是我将我的扑克手牌评估器抽象为 MWE 的尝试。实际上,letterFactory 将调用从Hand 派生的每个手牌类型类,并返回可以做出的最佳手牌(即对两对等)。
  • @shargors 我个人认为这个问题很清晰,但如果您认为可以改进,总是愿意接受提示?

标签: c++ oop polymorphism


【解决方案1】:

您没有返回您在letterFactory 中创建的派生类对象。相反,您将基类对象作为您在函数中声明的派生类对象的切片副本返回。

在这个返回的对象上调用myMethod 将调用SuperClass 中的实现,因为它最衍生的类型将是SuperClass

多态只适用于指针和引用。如果您希望您的类返回任一派生类类型,则它不能按值返回。您可以改为返回指向动态分配实例的指针:

std::unique_ptr<SuperClass> letterFactory(){
    if (which == "A") {
        return std::make_unique<SubClassA>();
    } else if (which == "B") {
        return std::make_unique<SubClassB>();
    } else {
        throw std::invalid_argument("Bad");
    }
}

【讨论】:

  • 相关链接:What is object slicing?.
  • 嗨@walnut,感谢您的回答-知道这与指针有关。您介意详细说明std::make_unique 在这里做什么吗?
  • @CiaranWelsh std::make_unique 为您动态分配并创建给定类型的对象,并将其置于std::unique_ptr 实例的控制之下,然后它会返回该实例。这样,您就不必编写return std::unique_ptr&lt;SubClassA&gt;{new SubClassA};,这很麻烦,因为它重复了两次类型名称,需要使用new,在可能的情况下应该不鼓励这样做,而且更容易出错,尤其是在异常方面安全。
猜你喜欢
  • 2014-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-09
相关资源
最近更新 更多