0

我的代码中有一个案例,我想使用对象切片,但我正在尝试确定这样做是否安全或聪明。为了确定这一点,我运行了以下示例:

#include <iostream>

using namespace std;


class Dog{

    public:
        Dog( int x )
            :x{x}
        {

        };

        int x;

};


class Spaniel: public Dog{

    public:
        Spaniel( int x, int y )
            :Dog{x}, y{y}
        {

        }

        int y;

};


class Green{

    public:
     Green( int q )
         :q{q}
     {

     }

     int q;

};


class GreenSpaniel: public Spaniel, public Green{

   public:
        GreenSpaniel( int x, int y, int q, int z )
            :Spaniel{x,y}, Green{q}, z{z}
        {

        }

        int z;

};



int main(){

    GreenSpaniel jerry{ 1,2,3,4 };

    Green fred = jerry;

    cout << fred.q << endl;  //correctly displays "3"

    return 0;

}

我期待它返回 1,因为基类不是最顶层(根),但它显示 3。所以,我的问题是它为什么/如何显示正确答案,这是一种安全的做法吗?如果任何一个类有虚拟表,你的答案会有什么变化?如果您认为它不安全,您是否有任何解决方法可以从派生对象复制非根基础对象?

我使用以下命令在 gcc 4.6.3 下的 linux 中运行它:

g++ -std=c++0x main.cc
4

1 回答 1

4

正在发生的事情是,fred 是使用编译器合成的复制构造函数构造的,该构造函数const Green&以参数为参数。它执行 jerry 的绿色部分内容的浅拷贝。

如果您使用,您会看到相同的结果

const Green& fred = jerry;

在没有执行复制的情况下,您只是通过将名称命名为 jerry 来访问 jerry 的部分fred

至于问题的另一部分,您的设计没有什么不安全的,只是它“复杂”,您需要了解正在发生的事情。您可能想阅读页面和相关页面,以了解有关该主题的一些讨论。

当然,您可以定义自己的具有不同行为的复制构造函数/操作符。或者你可以禁止编译器生成它们

处理这些问题的传统方法是声明私有复制构造函数和复制赋值,然后记录这样做的原因。在 C++2011 中引入了一个新的替代方案,声明了一个复制构造函数和一个复制赋值运算符,但将两者都标记为已删除。从 noncopyable 派生更简单、更清晰,并且不需要额外的文档。

资源

于 2013-07-23T08:36:06.487 回答