简体   繁体   English

C ++构造函数成员初始化器列表,对象切片

[英]C++ Constructor member initializer lists, Object Slicing

I have two classes 我有两节课

class A {

public:
    virtual void doStuff() = 0;
};

class B : public A {
    int x;

public:
    virtual void doStuff() override { x = x*2;} //just example function
};

And another class that modify and use data from the previous 还有另一个类可以修改和使用前一个数据

class Foo {
    A a;

public:
    Foo::Foo(A &a_) : a(a_) {}

};

now I create the objects, and passes to the Foo class 现在我创建对象,并传递给Foo类

B b;
// edit b attributes, 

Foo foo(b);

So at the argument list for the class constructor I know there is not the problem of object slicing, because is a reference, but what is the case at the moment of assign the variable a(a_) ? 因此,在类构造函数的参数列表中,我知道对象切片不是问题,因为它是一个引用,但是在分配变量a(a_)什么情况?

Since I don't know how much time the object b is going to live I need to make a secure copy. 由于我不知道对象b生存时间,因此我需要进行安全复制。 I have a lot of different derived classes from A, even derived from the derived. 我有很多来自A的派生类,甚至派生自派生类。

Will there be a object slicing?, 是否会有物体切片?,

Is there a solution to this, or I need to pass pointers (don't want this approach)? 有解决方案吗,还是我需要传递指针(不想使用这种方法)?

This causes slicing. 这导致切片。 C++ built in polymorphism only works with pointer/reference semantics. 内置多态的C ++仅适用于指针/引用语义。

In fact: 事实上:

class Foo {
  A a;

that won't even compile, because A is not a concrete class. 甚至不会编译,因为A不是具体的类。

To fix this, first make virtual ~A(){}; 要解决此问题,请首先使virtual ~A(){}; and then pass smart pointers to A around. 然后将智能指针传递给A Either unique or shared. 唯一或共享。


Failing that you can use your own bespoke polymorphism. 未能使用自己的定制多态性。 The easiers way is to stuff a pImpl smart pointer as a private member of a class and implement copy/move semantics in the holding class. 更简单的方法是将pImpl智能指针填充为类的私有成员,并在保持类中实现复制/移动语义。 The pImpl can have a virtual interface, and the wrapping class just forwards the non-overridable part of the behaviour to it. pImpl可以具有虚拟接口,包装类仅将行为的不可覆盖部分转发给它。

This technique can be extended with the small buffer optimization, or even bounded size instances, in order to avoid heap allocation. 为了避免堆分配,可以通过小的缓冲区优化甚至是有限大小的实例来扩展该技术。

All of this is harder than just using the built in C++ object model directly, but it can have payoff. 这不仅比直接使用内置的C ++对象模型困难,而且可以带来收益。

To see a famous example of this, examine std::function<Sig> which is a value type that behaves polymorphically. 要查看一个著名的示例,请检查std::function<Sig> ,它是一种表现多态的值类型。

There will be object slicing with what you currently have. 将使用您当前拥有的对象进行切片。 You're calling the A copy-constructor in Foo 's constructor, and there aren't virtual constructors. 您正在Foo的构造函数中调用A复制构造函数,并且没有虚拟构造函数。 Having a member variable of type A only reserves enough space within an instance of Foo for an instance of A . 具有成员类型A的成员变量仅在Foo实例内为A实例保留足够的空间。 There is only dynamic binding with pointers and references (which are pointers under the hood), not with member variables. 只有指针和引用(在幕后的指针)才动态绑定,而成员变量则没有。

You would have to use pointers to get around this or you could rethink whether you really need a set-up like this. 您将不得不使用指针来解决此问题,或者您可能会重新考虑是否真的需要这样的设置。

Yes, there is slicing. 是的,有切片。

There has to be slicing, because a B does not fit inside a A , but it is an A that you are storing inside the class Foo . 必须进行切片,因为B不能容纳在A ,但是要存储在类FooA The B part is "sliced off" to fit; B部分被“切掉”以适合; hence the name. 由此得名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM