虚函数问题

时间:2013-11-18 02:41:51

标签: c++

我有一个继承自Person的班级学生。 这两个类只有定义的虚函数printDetails()及其构造函数。

Person student = Student("John Smith", "a1234567");
student.printDetails();

当我在main中使用上面的代码时,在Person类中调用printDetails()函数。

Person* student = new Student("John Smith", "a1234567")
student->printDetails()

但是当我有动态分配的版本时,学生会调用该函数。

我的问题是,为什么在Person类中调用printDetails()而不是在第一段代码的Student 1中调用它?

3 个答案:

答案 0 :(得分:7)

Person student = Student("John Smith", "a1234567");

您的student不是Student。这是Person。你宣布它是这样的。当然,调用的函数是Person::printDetails

发生的事情被称为“切片”。有关详细信息,请参阅此常见问题解答:What is object slicing?

<强>更新
这回答了roybatty的问题“为什么第二个案例会调用Student::printDetails?”

第一种情况失去了对象为Student的所有细节。这就是当一个子类分配给父类时会发生什么。父类对象不知道子类添加的成员数据,也不知道子类重写的函数。它怎么样?

第二种情况并非如此。这是一个指向父类指针的指针。仍有一个Student对象与Parent*指针紧密相连,即使该指针是基类指针。如果与派生类的连接不存在,则声明成员函数virtual是没有意义的。

答案 1 :(得分:1)

你是所谓的对象切片的受害者。对象student的类型为Person,但它是使用应用于Person对象的Student的复制构造函数创建的。切片意味着失去Student的所有额外属性。

答案 2 :(得分:0)

要理解这个问题,你必须知道对象Person和Student是如何在内存中放置的。

考虑课程

class Person
{
protected:
    int age;

public:
    Person(int a)
    {
        age = a;
    }
    virtual void Print()
    {
        cout<<"Person Age : "<<age;
    }
};

class Student : public Person 
{
    int Id;

public:
    Student(int id, int age)
        :Person(age)
    {
        Id = id;
    }
    virtual void Print()
    {
        cout<<"Student Age : "<<age<<" Id : "<<Id;
    }
};

以下是对象布局Person和Student对象

-----------------------------------------------------
|_Virtual_Table_Ptr_Person | Data members of Person |
-----------------------------------------------------
-------------------------------------------------------------------------------
|_Virtual_Table_Ptr_Student | Data members of Person | Data Members of Student|
-------------------------------------------------------------------------------

因此,对于语句 Person student = Student(),临时对象 Student()的内存被复制到 student <的内存地址/ em>的。所以对象在这里切成薄片。然而_Vptr仍然是相同的(即人的VT)。