2

我想尽可能多地理解 C++。如果有基类B和派生类DD d;实例化派生对象。

  1. B & rb = d;,rb指派生对象d。这不会实例化基类的新对象。那么是rb指哪个内存部分呢?

  2. B newb = d;,这将调用将调用基类的复制构造函数。Objectd将首先与参数 type 绑定const B&,然后实例化一个新的基类对象。

  3. B newbb(static_cast<B>(d));,在这个声明中将完成什么?

以上三个陈述是我自己理解copy/move/conversion对象的方式。但他们真的让我很困惑。尽管我已经阅读了C++11 标准的相应部分,但我找不到有效且清晰的方法来解释代码。

我希望答案能用代码引用解释这三个语句。在对象复制/移动/转换期间发生了什么。


帮助!希望各位大神解答!!

4

1 回答 1

0

一般来说,这些都应该是复制操作,有时首先是转换。我将在下面介绍移动操作。

第 1 部分:我将要使用的语言可能与标准略有不同,但我倾向于认为rb是指整个对象d。我这么说的原因是,当我在做这样的事情时,D几乎总是至少有一个虚函数,并且任何通过调用的虚函数rb都会运行从 . 开始的版本D,而不是B. 例如,如果我们有:

class B
{
public:
    virtual int get_value() { return 10; }
};

class D: public B
{
public:
    virtual int get_value() { return 20; }
};

然后rb.get_value()将返回 20,而不是您可能想的 10。

第 2 部分:这实际上是您几乎不想做的事情。这里发生的情况是,通过称为“切片”的过程d将 转换为 a B,该过程丢弃D唯一的部分并仅留下B部分,然后将其复制到 create newb。这听起来很有用,但实际上您可能想要创建一个完整的副本d而不是部分副本,或者您根本不想创建一个副本而是想要使用指针或引用d.

如果你想创建一个完整的副本,你可能需要一个虚函数来做这个副本,像这样:

class B
{
public:
    virtual B *clone()
    {
        return new B(*this);
    }
};

class D: public B
{
public:
    virtual B *clone()
    {
        return new D(*this);
    }
};

第 3 部分:这与第 2 部分基本相同 - static_castjust 的存在使切片变得明确,而不是编译器自动执行的操作。同样,这可能不是您经常想要做的事情。


根据上下文,您正在使用的表达式可能会变成移动操作。例如,如果d即将被销毁,编译器可能会识别并调用移动函数而不是副本,因为移动通常更有效。例如:

B foo()
{
    D d;
    return d;
}

在 C++11 中,返回语句可能会调用移动构造函数(如果存在)而不是复制构造函数来创建返回值。也就是说,效果应该非常相似——在第 2 部分和第 3 部分中发生的切片将发生在调用两个构造函数中的任何一个。

于 2013-06-29T06:51:14.353 回答