2016-04-30 3 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);} 

в базе 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; 
    } 

И я все еще был поражен объективом slicind. Я пробовал различные вещи/подходы/методы, и все это привело к разделению объектов.

Есть ли способ, как создать такую ​​вещь (карту, которая содержит 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(); 
} 
+1

что вы имеете в виду «используя новое ключевое слово в качестве В параметре функционировать» ?? Если вы хотите избежать нарезки объектов, просто передайте указатель или ссылку .... – user463035818

+0

Не могли бы вы показать пример? Я пытался заставить его работать в течение нескольких часов n, и я пробовал передавать ссылку и указатель без успеха – Darlyn

ответ

2

Измените add() функцию, чтобы принять его параметр по ссылке:

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

Вы нарезка объекта, когда вы передаете его по значению. Это копирует и разрезает его. Вместо этого вам нужно передать параметр как ссылку.

Все ваши методы clone() уже постоянные. Хорошо.

+0

он все еще нарезает печать только «Person ..» – Darlyn

+0

Вы действительно не показывали, как вы объявили свои методы clone(). Вы только перефразировали это. Таким образом, любой ответ был бы предположением, в лучшем случае. В любом случае для этого используется отладчик. Пройдите через свой код, за строкой и посмотрите, какой метод объекта clone() запускается. –

+0

Я написал, как я объявил функцию clone(), в моем quetion есть целая декларация. – Darlyn

0

изменения надстройка(), чтобы получить Person аргумент, *

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

изменения как передать объект функции add() к объектам выделенных в свободном магазине.

Определите свой собственный конструктор копирования в классе Person

+0

Что вы подразумеваете под этим, isnt clone() function enought? Не могли бы вы привести пример? – Darlyn

+0

API, вроде 'void add (std :: unique_ptr )', кажется, предлагает себя. –

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