函数 return 不同类型

Function return different types

给定一个基本结构和派生结构,我想编写一个方法,可以 return 它们中的任何一个取决于一些输入,例如 int、字符串等

到目前为止,我尝试了各种代码片段,如下所示:

struct Base {
    std::string name = "Base";
};

struct Derived1 : Base {
    std::string name = "Derived1";
};

struct Derived2 : Base {
    std::string name = "Derived2";
};

template<class T>
T string_to_struct(std::string s) {
    if(s== "Derived1") {
        return Derived1();
    } else if(s == "Derived2") {
        return Derived2();
    } else {
        return Base();
    }
}

在 main 中我调用函数:

void test2() {
    std::string s = "Derived1";
    auto bb = string_to_struct<Base>(s);
    std::cout << bb.name << std::endl;
}

现在我希望打印 "Derived1" 如果 s 匹配 "Derived1","Derived2" 如果它等于 "Derived2" 等等。但是,上面的代码不起作用,并且 string_to_struct return 在任何情况下都是 "Base" 的实例。我该如何解决?

string_to_struct 总是 returns a Base 按值(因为你要求那个)。由于 bb 的静态类型是 Base,因此 bb.name 总是引用 Base::name。并且由于您按值 return,因此 bb 的动态类型也将始终为 Base.

您需要做两件事才能得到您想要的:

  1. 不要通过 Base 值 return 多态对象。如果它们是在函数中创建的,最好的 return 值将是 std::unique_ptr<Base>。原因:您需要引用或指针才能使多态工作。

  2. 不要使用依赖对象静态类型的访问,例如.name。您想使用 bb 动态类型 ,这最容易用虚方法实现,例如:

    virtual std::string getName() const
    

    与依赖(非常脆弱的)名称隐藏相比,这也是一种更清洁的解决方案。

上述情况下的最佳情况是使用 static_cast。相应的代码片段将如下所示:

Base* string_to_struct7(std::string s) {
    if(s== "Derived1") {
        return new Derived1();
    } else if(s == "Derived2") {
        return new Derived2();
    } else {
        return new Base();
    }

然后进行进一步处理:

auto t = string_to_struct7(s);
auto bb7 = static_cast<Derived1*>(t);
std::cout << bb7->name<< std::endl;

这正是我想要的。派生 class 成员现在可以直接寻址。

Max Langhof 的回答当然也是有效的。像 getter 方法一样简单地使用 Java 方法是可行的,但缺点是它们必须在每个 class 中为每个 class 成员定义,这很快就会失控。

更多信息也可以在这里找到:C++ Access derived class member from base class pointer

编辑:第三种方法是在 Derived 类 和虚拟 getter 方法中使用包装器对象。目前我想不出缺点 - 除了丑陋。