如何克服对象切片的方法

时间:2016-04-30 18:02:43

标签: c++ oop inheritance polymorphism object-slicing

有没有办法如何离开,克服对象切片而不使用新关键字作为参数来运行?我有基础对象

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

in base clase

并在派生类中声明了

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

我还被一个物体切片击倒了。我尝试了各种各样的东西/方法/方法,所有这些都导致了对象切片。

有没有办法如何创建这样的东西(包含基类的derivec类的映射)而不在函数的参数中使用new关键字,例如

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

3 个答案:

答案 0 :(得分:2)

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

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

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

您的所有clone()方法已经不变。好。

答案 1 :(得分:0)

更改你的add()以通过*

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

更改将对象传递给add()函数的方式,以及在免费商店中分配的对象。

Person

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

答案 2 :(得分:0)

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

{{1}}