虚方法不调用派生类方法。 - C ++

时间:2011-12-01 22:04:57

标签: c++ inheritance virtual

我在基类和派生类中都有一个方法。当我在派生类中的对象上调用此方法时,它调用基类方法而不是派生类方法。这是我的代码:

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

当在Student对象上调用coutPerson()方法时,它只会播放名称,birthday,phoneNumber和city&amp;州。这段代码有什么问题?它应该调用Student coutMethod ...

谢谢!

3 个答案:

答案 0 :(得分:7)

您可能会在某个时刻将Student对象复制到Person对象,从而导致Object Slicing Problem。例如,您可能将它们存储在vector<Person>中。您需要使用指针或引用,而不是复制对象。

要解释为什么这是一个问题,您必须意识到向量不存储您在push_back中传递给它的实际对象,它存储对象的副本。将Student复制到Person时,副本不再是Student

答案 1 :(得分:3)

您的personVector包含Person个对象。不是对Person个对象的引用,而是对实际的Person个对象的引用。当你“将Student对象放入向量”时,真正发生的是向量构造一个 new Person对象,该对象使用{{1进行复制初始化您赋予它的对象,也就是说,它会创建Student对象的Person部分的副本。此行为也称为“切片”。

由于向量中没有Student个对象,但只有Student个对象,因此调用Person上的coutPerson调用Person::coutPerson而不是{{}就不足为奇了1}}。

如果您需要多态行为,则必须在容器中存储指针(最好是智能指针,如Student::coutPersonshared_ptr)。但请注意,您在函数中构造的对象unique_ptr在返回时被销毁,因此为了使对象生存(因此您可以指向它),您必须使用p分配它。

答案 2 :(得分:1)

功能很好。您要么从coutPerson类型的对象调用Person,要么从Person的构造函数/析构函数中调用它(感谢@celtschk)。 您应该通过指针引用调用Person类型的对象。这就是你如何获得多态性。