Виртуальный метод не вызывает метод класса dervied.- C ++ - PullRequest
1 голос
/ 02 декабря 2011

У меня есть метод как в базовом классе, так и в производном классе.Когда я вызываю этот метод для объекта в производном классе, он вызывает метод базового класса, а не метод производного класса.Вот мой код:

Person.h

class Person
{
...
public:
...
    virtual void coutPerson();
};

Person.cpp

void Person::coutPerson() {
    cout << name << endl;
    birthday.coutDate();
    phoneNumber.coutPhoneNumber();
    cout << city << ", " << state << endl;
}

Student.h

class Student : public Person
{
...
public:
...
    virtual void coutPerson();
};

Student.cpp

void Student::coutPerson() {
    cout << "DEBUG: Student::coutPerson()" << endl;
    //Person::coutPerson();
    cout << "Dorm Room: " << this->dorm << " " << this->dormRoom << endl;
}

Объект, созданный в: addPerson<Student>(personVector); Когда объект создается, он создается как Студент, потому что он вызывает студента-конструктора.Метод вызывается по адресу: personVector[num-1].coutPerson(); Объект Student - это объект, который сообщается coutPerson, поскольку он отображает информацию, которую я дал ему при создании объекта Student.

template<typename T> void addPerson(vector<Person> &personVector) {
    T p;
    personVector.push_back(p);
}

Когда метод coutPerson ()вызывается для объекта Student, он содержит только имя, день рождения, phoneNumber, город и штат.Что не так с этим кодом?Стоит позвонить Студенческому Методу ...

Спасибо!

Ответы [ 3 ]

7 голосов
/ 02 декабря 2011

Возможно, вы в какой-то момент копируете объект Student в объект Person, что приводит к проблеме нарезки объектов .Например, вы можете хранить их в vector<Person>.Вам нужно использовать указатель или ссылку вместо копирования объекта.

Чтобы объяснить, почему это проблема, вы должны понимать, что вектор не хранит фактический объект, который вы ему передаете, в push_back,он хранит копию объекта.Когда вы копируете Student в Person, копия больше не является Student.

3 голосов
/ 02 декабря 2011

Ваш personVector содержит Person объектов. Не ссылки на Person объекты, а реальные Person объекты. Когда вы «помещаете свой Student объект в вектор», то на самом деле происходит то, что вектор создает новый Person объект, который инициализируется копией с Student объектом, который вы ему даете то есть он создает копию части Person объекта Student. Такое поведение также известно как «нарезка».

Поскольку в векторе нет объекта Student, а есть только объект Person, неудивительно, что вызов coutPerson для него вызывает Person::coutPerson, а не Student::coutPerson.

Если вам нужно полиморфное поведение, вы должны хранить указатели (предпочтительно умные указатели, такие как shared_ptr или unique_ptr) в контейнере. Однако обратите внимание, что объект p, который вы создали в своей функции, уничтожается при возврате, поэтому для того, чтобы объект выжил (чтобы вы могли иметь указатель на него), вы должны выделить его с помощью new.

1 голос
/ 02 декабря 2011

Функции в порядке.Вы либо вызываете coutPerson из объекта типа Person, либо вызываете его из конструктора / деструктора Person (спасибо @celtschk).
Вы должны вызывать через указатель 1006 * или ссылка на объект типа Person.Вот так и получается полиморфизм.

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