我有两个类,一个是从另一个类派生的。我想要一个函数,该函数返回调用派生虚拟函数的基类的对象(而不是指针或引用)。
#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()
中注释掉了取消引用向上指针的代码。奇怪的是,它可以正确打印!如果我将其转换为对象,则不会!
对于所有这一切为何发生的见解,将不胜感激。
答案 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;
};