一种克服对象切片的方法

A way how to overcome object slicing

本文关键字:对象 切片 方法 克服 一种      更新时间:2023-10-16

有没有一种方法可以在不使用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();

由于对象切片,它打印

"人…"

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

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

碱性

在派生类中,我声明了

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

我仍然被一个物体切片机卡住了。我尝试过各种各样的东西/方法/方法,所有这些都导致了对象切片。

有没有一种方法可以在函数的参数中不使用new关键字来创建这样的东西(包含基类的derivec类的映射),例如

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()函数以通过引用接受其参数:

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

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

您的所有clone()方法都已是常量。好的

通过*更改add()以获取Person参数

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

更改将对象传递给add()函数的方式,以将对象传递到空闲存储中分配的对象。

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

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

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