Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/118.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么切片非根基类会得到正确的答案?_C++_C++11_Multiple Inheritance_Object Slicing - Fatal编程技术网

C++ 为什么切片非根基类会得到正确的答案?

C++ 为什么切片非根基类会得到正确的答案?,c++,c++11,multiple-inheritance,object-slicing,C++,C++11,Multiple Inheritance,Object Slicing,我的代码中有一个例子,我想使用对象切片,但我试图确定这样做是安全的还是明智的。为了确定这一点,我运行了以下示例: #include <iostream> using namespace std; class Dog{ public: Dog( int x ) :x{x} { }; int x; }; class Spaniel: public Dog{ publ

我的代码中有一个例子,我想使用对象切片,但我试图确定这样做是安全的还是明智的。为了确定这一点,我运行了以下示例:

#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;

}

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

如果您使用

const Green& fred = jerry;
如果没有进行复制,您只需访问jerry的jerry部分,将其命名为
fred

至于问题的另一部分,你的设计没有什么不安全的地方,只是它很“复杂”,你需要知道发生了什么。您可能需要阅读和相关页面,以便对该主题进行一些讨论

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

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


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

如果您使用

const Green& fred = jerry;
如果没有进行复制,您只需访问jerry的jerry部分,将其命名为
fred

至于问题的另一部分,你的设计没有什么不安全的地方,只是它很“复杂”,你需要知道发生了什么。您可能需要阅读和相关页面,以便对该主题进行一些讨论

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

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



它可能既不安全也不智能,但它是确定性的:
Green
copy构造函数复制
jerry
对象的
Green
子对象,该对象的
q
设置为
3
。您知道标准中有一节解决了这一问题(即保证其确定性吗?)否,这不是一种安全的做法,人们通常喜欢避免切片,因为切片会带来问题。虽然您的程序定义得很好(请参见下面的答案),但将成员变量保留为public并不是一种安全的做法,它将使用赋值(C++11 4.10/3(指针转换))以静默方式重写(通常不是我们所希望的)它可能既不安全也不智能,但是它是确定性的:
Green
copy构造函数复制您的
jerry
对象的
Green
子对象,该对象的
q
设置为
3
。您知道标准中有一部分解决了这一问题(即保证其确定性吗?)。不,这不是一种安全的做法,人们通常喜欢避免切片,因为切片会带来问题。虽然你的程序定义得很好(见下面的答案),但将成员变量保留为public并不是一种安全的做法,它将被赋值悄悄地覆盖(通常不是我们所希望的)(没有错误或警告)。我想说,C++11 4.10/3(指针转换);结果仍然是3?你知道在gcc中生成编译器生成的构造函数的方法吗?出于同样的原因:Green fred(jerry)通过调用复制构造函数(将jerry作为参数传递)来构造一个Green类型的对象。我认为没有办法。编译器生成的远远不止这些,我还猜测,因为它是一个引用,所以带有vtable的类不会有什么不同;结果仍然是3?你知道在gcc中生成编译器生成的构造函数的方法吗?出于同样的原因:Green fred(jerry)通过调用复制构造函数(将jerry作为参数传递)来构造一个Green类型的对象。我认为没有办法。编译器生成的远远不止这些,我还猜测,因为它是一个引用,所以带有vtable的类不会有什么不同?