一种克服对象切片的方法

A way how to overcome object slicing

有没有办法在不使用 new 关键字作为参数的情况下摆脱、克服对象切片?我有基础对象

class Person{
    public:
        Person(string name , int age ){
            this -> name = name;
            this -> age  = age;
        }
        virtual void getInfo(){
            cout << "Person " << name << " " << age;
        }
        void add( string name , Person a){
            Person *one = new Person(a);
            m[ name ] = one;
        }
        void print(){
            for( auto &x: m )
                 x.second -> getInfo()
        }
    protected:
        string name;
        int age;
       map< string , Person*> m;
    };

派生对象

class Kid : public Person{
public:
    Kid(string name, int age):Person(name,age){};
    virtual void getInfo( ){
        cout << "Kid " << name << " " << age;
    }
};
 class Adult : public Person{
    public:
        Adult(string name, int age):Person(name,age){};
        virtual void getInfo( ){
            cout << "Adult " << name << " " << age;
        }
    };

并尝试调用它,例如

   Person one("John", 25);
   one.add("first",Kid("Mathew",15));
   one.add("second",Adult("Leo",55));
   one.print();

由于对象切片,它打印

"Person..."

我试过使用 unique_ptr 并得到了相同的结果。 我尝试声明 copy function 例如

vitual clone() const{ return new Person(*this);}

在基类中

并且在导出的 classes 中我声明了

Kid* clone() const{ return new Kid(*this);}
Adult* clone() const{ return new Adult(*this);}

并编辑了添加函数。

    void add( string name , Person a){
        Person *one = a.clone();
        m[ name ] = one;
    }

我仍然被对象切片击倒了。我尝试了各种 things/approaches/methods 并且都导致了对象切片。

有没有办法在函数的参数中不使用 new 关键字,例如 [=22] =]

Person one("bla",5);
one.add("asd", new Kid("one",15))

感谢您的帮助。

// 代码的当前状态

class Person{
    public:
        Person(string name , int age ){
            this -> name = name;
            this -> age  = age;
        }
        virtual void getInfo(){
            cout << "Person " << name << " " << age;
        }
        void add( string name , const Person &a){
            Person *one = a.clone();
            m[ name ] = one;
        }
        void print(){
            for( auto &x: m ){
                 x.second -> getInfo();
                 cout << endl;
            }
        }
         virtual Person* clone() const{ return new Person(*this);}

    protected:
        string name;
        int age;
        map< string , Person*> m;
    };

class Kid : public Person{
    public:
        Kid(string name, int age):Person(name,age){};
        virtual void getInfo( ){
            cout << "Kid " << name << " " << age;
        }
        Kid* clone() const{ return new Kid(*this);}
    };
 class Adult : public Person{
    public:
        Adult(string name, int age):Person(name,age){};
        virtual void getInfo( ){
            cout << "Adult " << name << " " << age;
        }
        Adult* clone() const{ return new Adult(*this);}
    };

int main(){
     Person one("John", 25);
   one.add("first",Kid("Mathew",15));
   one.add("second",Adult("Leo",55));
   one.print();
}

更改您的 add() 以通过 *

获取 Person 参数
void add( string name , Person* a ){
    m[ name ] = a;
}

将对象传递给 add() 函数的方式更改为在自由存储上分配的对象。

Personclass

中定义自己的复制构造函数

更改您的 add() 函数以通过引用接受其参数:

void add( string name , const Person &a){
    Person *one = a.clone();
    m[ name ] = one;
}

当您按值传递对象时,您正在对对象进行切片。复制并切片它。您需要将参数作为参考传递。

你所有的 clone() 方法都已经是常量了。好

如果你不想让你的对象被切片,你只需通过引用或指针传递:

struct Foo { 
    virtual void print() const {std::cout << "FOO" <<std::endl;} 
};
struct Bar : Foo { 
    void print() const {std::cout << "BAR" <<std::endl;} 
};

void slicingFunc(Foo foo){ foo.print(); }
void nonSlicingFunc(const Foo& foo) { foo.print(); }


int main() {
    Bar b;
    slicingFunc(b);    // prints FOO
    nonSlicingFunc(b); // prints BAR
    return 0;
}