在复制构造函数中防止切片 [英] Preventing slicing in copy constructor

查看:80
本文介绍了在复制构造函数中防止切片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想复制一个向量类型为Foo的对象,但是这些对象可以是几种不同的Foo派生类型.我不知道如何切片而不进行复制.这是我的玩具代码

I want to copy a vector of type Foo objects but the objects can be several different derived types of Foo. I can't figure out how to copy without slicing. Here's my toy code

#include "stdafx.h"
#include <memory>
#include <vector>
#include <string>
#include <iostream>

class Foo
{
public:
    Foo() { m_x = "abc"; }
    Foo( const Foo &other ) { m_x = other.m_x; }
    virtual std::string ToString() { return m_x; }
    std::string m_x;
};

class FooDerivedA : public Foo
{
public:
    FooDerivedA() : Foo() { m_y = 123; }
    std::string ToString() { return m_x + ", " + std::to_string( m_y ); }
    int m_y;
};

class FooDerivedB : public Foo
{
public:
    FooDerivedB() : Foo() { m_z = true; }
    std::string ToString() { return m_x + ", " + std::to_string( m_z ); }
    bool m_z;
};

class Foos
{
public:
    Foos(){}
    Foos( const Foos &other )
    {
        for ( auto &foo : other.m_Foos )
        {
            // I believe this is slicing. How can I prevent this?
            auto f = std::unique_ptr<Foo>( new Foo( *foo ) ); 
            m_Foos.push_back( std::move( f ) );
        }
    }
    void Add( std::unique_ptr<Foo> foo ) { m_Foos.push_back( std::move( foo ) ); }
    std::string ToString() 
    {
        std::string s;
        for ( auto &foo : m_Foos )
        {
            s += foo->ToString() + "\n";
        }
        return s;
    }
private:
    std::vector<std::unique_ptr<Foo>> m_Foos;
};

int main()
{
    Foos f1;
    f1.Add( std::unique_ptr<FooDerivedA>( new FooDerivedA ) );
    auto f2 = Foos( f1 );
    std::cout << "f1:" << f1.ToString() << std::endl;
    std::cout << "f2:" << f2.ToString() << std::endl;
    system("pause");
    return 0;
}

我无法指定该类型应为FooDerivedA,例如:

I can't specify that the type should be FooDerivedA like:

auto f = std::unique_ptr<Foo>( new FooDerivedA( *foo ) ); 

因为它可能是FooDerivedB.如何在不切片的情况下复制数据?

because it might be FooDerivedB. How can I copy the data without slicing?

推荐答案

解决此问题的经典方法是实现virtual Foo *clone() const,然后调用它代替副本构造函数.

The classical method to solve this problem is to implement a virtual Foo *clone() const, which is then called instead of the copy constructor.

因此,如果我们在x中有一个Foo(源自)形式的对象,则可以通过以下方式创建另一个对象:

So, if we have an object of some (derived form of) Foo in x, we can create another one by:

 void someFunc(Foo *x)
 {
     Foo *copy_of_x = x->clone();
     ... 
     delete copy_of_x;  // Important so we don't leak!
 }

请注意,由于它是一个虚函数,因此我们不能在foo或其任何派生类型的构造函数中调用它,因为虚函数在构造函数中无法正确"运行.

Note that since it's a virtual function, we can't call it in the constructor of foo or any of it's derived types, as virtual functions don't operate "correctly" inside constructors.

这篇关于在复制构造函数中防止切片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆