Изменить тип объекта на основе наследования - PullRequest
1 голос
/ 25 января 2020

У меня есть класс Person:

class Person {
public:
    int Age;
    int ID;
};

И у меня есть 2 класса: Adult и Child, которые наследуют Person:

class Child : Person{
public:
    Child();
    void print_ms_child(){
        cout << "I'm an child";
    }
};

class Adult : Person{
public:
    Adult(); 
    void print_ms_Adult(){
        cout << "I'm an adult";
    }
};

Я хочу объявить объект Person

int main() {
    Person my_Person;
    my_Person.Age = 10;
    my_Person.ID = 013272;

А затем используйте условия, чтобы установить его тип.

    if(my_Person.Age > 18){
        my_Person = new Adult(); // this won't work
    }
    else{
        my_Person = new Child(); // this won't work
    }

Я полагаю, это возможно, но я не знаю правильный синтаксис для этого ( Как Я так делаю? ). (Извините за публикацию кода, который даже не будет компилироваться)

Но также , я хочу измениться с Child на Adult в случае изменения Age (я даже не уверен, что это возможно).

    my_Person.Age = 21;
    my_Person = new Adult(); // this won't work

Ответы [ 2 ]

1 голос
/ 25 января 2020

Сначала я бы определил ваш класс Person следующим образом:

class Person {
    int Age;
    int ID;
protected:
   Person(int age, int id): Age{age}, ID{id} {}
public:
   virtual ~Person() = default;
};

То есть конструктор Person сделан protected, так что класс вне иерархии не может быть создан объект Person и его деструктор сделаны virtual, чтобы сделать его пригодным в качестве базового класса для типа polymorphi c.

Затем оба Child и Adult публично наследуются от Person, как они у вас уже есть. Их конструкторы в итоге вызывают конструктор Person с той же параметризацией, которую получают их конструкторы:

class Adult: public Person {
public:
   Adult(int age, int id): Person(age, id) {}
   // ...
};

class Child: public Person {
public:
   Child(int age, int id): Person(age, id) {}
   // ...
};

Наконец, для создания объектов, производных от Person, я бы создал фабричную функцию ниже:

std::unique_ptr<Person> create_person(int age, int id) {
   if (age < 18)
      return std::make_unique<Child>(age, id);
   else
      return std::make_unique<Adult>(age, id);
}

Эта фабричная функция создает объект Child, если возраст создаваемого лица меньше 18 лет. В противном случае он создает объект Adult. Это - определение типа создаваемого объекта - выполняется во время выполнения.


EDIT: Вы задались вопросом, как объект Child может стать объектом Adult после его возраст достиг 18 лет.

Я бы предложил сделать состояние Person объекта неизменным , чтобы каждый раз при создании возраста создавался новый * fre sh объект. человека увеличивается. Таким образом, создание нового объекта из существующего будет единственным способом увеличить возраст Person, и в этот момент у вас будет возможность решить, создавать ли объект Child или Adult на основе новой эры.

Для этого сначала квалифицируйте элемент данных Age в Person как const (вы можете сделать то же самое с ID). Затем определите следующую функцию-член Person, которая всегда создает новый объект (с тем же ID) в результате увеличения объекта Person Age на единицу:

std::unique_ptr<Person> Person::increase_age() const {
   return create_person(Age + 1, ID);
}

Как видите, он делегирует создание объекта фабричной функции, create_person(), уже объясненной выше. Эта функция-член может вызываться как для объектов Child, так и Adult, поскольку она наследуется от Person.

0 голосов
/ 25 января 2020

Вы не можете изменить тип переменной после ее объявления. C ++ является статически типизированным языком . my_person является Person. Вы не можете это изменить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...