将转换指针转换为调用派生虚拟的基础对象

时间:2019-03-03 20:29:29

标签: c++

我有两个类,一个是从另一个类派生的。我想要一个函数,该函数返回调用派生虚拟函数的基类的对象(而不是指针或引用)。

#include <iostream>
using namespace std;

class Base
{
public:
    virtual void print() { cout << "Base" << endl; }
};

class Derived : public Base
{
public:
    void print() { cout << "Derived" << endl; }
};

Base go()
{
    Derived *derived = new Derived();

    Base *base = derived;
    base->print();

    // (*base).print(); // prints "Derived" !
    // Base base2 = (*base);
    // base2.print(); // prints "Base" !

    return *base;
}

int main()
{
    Base base = go();
    base.print();
    return 0;
}

这将打印出来

Derived
Base

因此,在go()函数中,我设法将其转换为Base,并且打印正常。但是当我返回对象时,打印使用的是基本功能!

我知道如果您返回一个指针或引用,这是可行的,但是我确实需要返回一个对象。这可能吗?为什么我的代码不起作用?

如您所见,我已经在go()中注释掉了取消引用向上指针的代码。奇怪的是,它可以正确打印!如果我将其转换为对象,则不会!

对于所有这一切为何发生的见解,将不胜感激。

2 个答案:

答案 0 :(得分:2)

当您返回实际对象(而不是引用或指针)时,它将调用其副本ctor。在这种情况下,您将返回一个基类,因此它将调用其副本构造函数并创建一个 new 基类对象。

#include <iostream>
using namespace std;

class Base
{
public:
    Base() = default;
    Base(const Base & base) { std::cout << "COPY BASE" << std::endl; }
    virtual void print() { cout << "Base" << endl; }
};

class Derived : public Base
{
public:
    Derived() = default;
    Derived(const Derived & derived) { std::cout << "COPY DERIVED" << std::endl; }
    void print() { cout << "Derived" << endl; }
};

Base go()
{
Derived *derived = new Derived();

Base *base = derived;
base->print();

// (*base).print(); // prints "Derived" !
// Base base2 = (*base);
// base2.print(); // prints "Base" !

return *base;
}

int main()
{
    Base base = go();
    base.print();
    return 0;
}

在这种情况下,输出将是: 派生 COPY BASE, 基本

答案 1 :(得分:1)

通过返回base对象本身,您将删除对该对象的所有引用,这些引用以derived开始,随后被上载(并复制)。

如此有效,您追求的目标将无法正常工作。


如果您真的“需要返回对象”,我建议使用薄包装纸

struct karls_return_object {
    // ... stuff ...

    Base *b;
};