理解虚拟复制构造函数

4

我在学习C++的时候,阅读一本书时遇到了难以理解的代码。以下是代码:

class Base
{
    public:
        Base() {};
        virtual ~Base() {};

        virtual Base* Clone() {return new Base(*this);}
};

class Derived
{
    public:
        Derived() {};
        virtual ~Derived() {};

        virtual Base* Clone() {return new Derived(*this);}
};

在这个 Clone() 函数中,我了解到这个函数返回一个指向基类对象的指针。但是我不理解函数内部发生了什么。之前当我使用 new 时,如 int *pInt = new int, 我的理解是 new 在堆上为整型分配足够的内存空间,然后返回该地址,并将其应用于指针 pInt。根据同样的逻辑,我试图理解代码中的 new Derived(*this) 部分。所以我认为它在堆上为派生类对象分配足够的内存空间,并返回该地址,然后由 Clone() 函数返回。

但是,为什么要通过构造函数传递*this 呢?如果那是一个构造函数,我了解 *this 意味着正在克隆的任何对象的地址,但我不理解在 new 函数的上下文中 class_name(address_of_an_object) 的语法。

请问有人可以解释一下那部分的内容吗?

先行谢过。

1个回答

10
误解在这里:
* this表示传递了被克隆对象的地址
实际上,this是被克隆对象的地址,但* this(请注意星号)是对该地址进行取消引用的结果。因此,* this的类型为Derived&,它是对被克隆对象的引用,而不是它的地址。
因此,调用new Derived(* this)意味着动态分配空间之后(这是new所做的),使用拷贝构造函数Derived(const Derived&)初始化新空间,在本例中其实并没有自定义,因此使用了(编译器生成的)默认版本的拷贝构造函数。
为了澄清new的语义:如果C是一个类,则
new C;

为类型C分配足够的空间,并调用类型C的构造函数来初始化该空间。这是new语义的一部分:它总是调用构造函数来初始化新分配的空间。

当您调用

new C(a,b,c);
以一些参数abc调用new,那么它将调用一个接受这三个参数的C构造函数。如果未定义此类构造函数,则会得到编译器错误。
现在特殊情况是您调用:
new C(a);

如果使用类型为C&的参数a,那么new将像往常一样调用相应的构造函数。适当的构造函数可以是C(C &)(如果定义了),也可以是C(const C&)(由编译器自动定义的复制构造函数)。


谢谢回复。我想我不太明白如何用'new'“调用复制构造函数”。如果'Derived(*this)'仅仅是被克隆对象的引用,那么'new'如何调用复制构造函数呢?我认为'new'只是分配内存并返回地址,这不是事实吗? - EindacorDS
3
new 总是会调用构造函数。new Derived() 调用默认构造函数,new Derived(1,2) 调用了不存在的构造函数 (int,int) ,而 new Derived(*this) 则调用了隐式复制构造函数。每当你有一个这样的构造函数 _ClassName(const ClassName&)_,它就是一个复制构造函数,如果你传递一个 ClassName 对象来构造另一个 ClassName 对象,那么它将被复制。 - André Puel
@user1997615 就像André所说的那样。我还在答案中添加了一个澄清。 - jogojapan
1
非常感谢你们的澄清,这节课现在更加容易理解了。非常感谢你们的帮助。 - EindacorDS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接