从虚拟方法返回派生对象作为基础

Returning derived object as base from virtual method

本文关键字:对象 为基础 派生 返回 虚拟 方法      更新时间:2023-10-16

基类中有一些虚拟方法返回同一基本对象(不是指针(。在某些虚拟覆盖中,我想返回派生的对象作为基础。但是问题是,方法总是会从返回派生中创建基本对象。这是简单的示例:

#include <iostream>
#include <string>
class Base {
public:
    Base() {}
    virtual std::string myName() { return "Base"; }
    virtual Base createAlike() { return Base(); }
};
class Derived : public Base {
public:
    Derived() : Base() {}
    std::string myName() override { return "Derived"; }
    Base createAlike() override { return Derived(); }
};
int main() {
    Derived d;
    Base d1 = d.createAlike();
    std::cout << d.myName() << std::endl;
    std::cout << d1.myName();
    return 0;
}

输出:

Derived
Base

如何纠正它?

由于您按值返回,返回值是您返回的表达式的副本。由于该返回类型始终是Base,因此Derived对象被切成薄片。为了使多态性起作用,您通常需要指针或参考。

使用std::unique_ptr尝试一下:

#include <iostream>
#include <string>
#include <memory>
class Base {
public:
    Base() {}
    virtual std::string myName() { return "Base"; }
    virtual std::unique_ptr<Base> createAlike()
    { return std::make_unique<Base>(); }
};
class Derived : public Base {
public:
    Derived() : Base() {}
    std::string myName() override { return "Derived"; }
    std::unique_ptr<Base> createAlike() override
    { return std::make_unique<Derived>(); }
};
int main() {
    Derived d;
    auto d1 = d.createAlike();
    std::cout << d.myName() << std::endl;
    std::cout << d1->myName();
    return 0;
}