2016-04-30 45 views
1

有没有办法如何离开,克服对象切片而不使用新的关键字作为参数功能?我有基本对象一种方法如何克服对象切片

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

而我仍然被一个对象切片击倒。我尝试了各种各样的东西/方法/方法,并且都导致了对象切片。

有没有办法如何创建这样的事(图保存derivec类的基类),而在函数的参数e.g

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

感谢您的帮助使用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 , 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(); 
} 
+1

你是什么意思与“使用new关键字作为paramater运作”?如果你想避免对象切片只需传递一个指针或引用.... – user463035818

+0

你能举个例子吗?我一直试图让它工作几个小时ñ,我试图通过参考和指针没有成功 – Darlyn

回答

2

更改add()功能参考接受它的参数:

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

您切片对象,当你按值传递。复制并切片。相反,您需要传递参数作为参考。

您所有的clone()方法已经是恒定的。好。

+0

它仍然得到切片打印只有“人..” – Darlyn

+0

你没有真正显示你如何宣布你的clone()方法。你只解释它。所以,任何答案都是最好的猜测。无论如何,这是调试器的用途。逐行浏览您的代码,并查看调用了哪个对象的clone()方法。 –

+0

我的确写过我如何宣布clone()函数,在我的伫列中有一个完整的声明。 – Darlyn

0

改变你的add()的当前状态,通过得到人的说法*

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

变化如何传递对象到add()函数对象在免费商店分配。

定义自己的拷贝构造函数在Person

+0

你是什么意思,isnt clone()函数enought?你能举个例子吗? – Darlyn

+0

类似'void add(std :: unique_ptr )'的API似乎暗示了它自己。 –

0

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

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