对象数组中通过虚函数表调用虚函数

我有一个person类,并从其中派生出了一个students类。
我想要通过虚函数表调用函数得到最高分学生的年龄,id号和分数。
我尝试用...&stu[i]+2)来得到getscore(),但是失败了.当我调试的时候,我发现+2可以得到getid(),+4可以得到getscore().
此外,每次我调用函数的时候,明明写的是&stu[i],得到的结果却都是&stu[0].这个代码还会引发一个segmentation fault。我不知道为什么,有人能找出原因和解决办法吗,谢谢。

Sample input:
    3

    17 1234543 76
    18 1234567 79
    18 1234590 87

Sample output:
    18 1234590 87

下面是源代码

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

class Person{
    private:
        int age;

    public:
        virtual int getage() { return age; }
        void setage(int age){
            this->age = age;
        }
};

class Student : public Person{
    private:
        int id;
        int score;
        virtual int getid() { return id; }
        virtual int getscore() { return score; }

    public:
        void set(int age, int id, int score){
            setage(age);
            this->id = id;
            this->score = score;
        }
};

typedef int (*pscore)();
typedef int (*pid)();

int main()
{
    int n;
    cin >> n;
    Student stu[20];
    int age, idnumber, mark;
    for (int i = 0; i < n; ++i){
        cin >> age >> idnumber >> mark;
        stu[i].set(age, idnumber, mark);
    }

    pscore ppscore;
    pid ppid;

    int max = -1, temp = -1;
    for (int i = 0; i < n; ++i){ 
        ppscore = (pscore) * ((int *)*(int *)(&stu[i])+4);
        temp = ppscore();
        if (max < temp)
        {
            max = temp;
        }
    }

    for (int i = 0; i < n; ++i){
        ppscore = (pscore) * ((int *)*(int *)(&stu[i]) + 4);
        if (max == ppscore()){
            ppid = (pid) * ((int *)*(int *)(&stu[i]) + 2);
            cout << " " << ppid() << " " << max << endl;
        }
    }
    system("pause");
    return 0;
}

another

#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;

class Person
{
private:
    int age;

public:
    virtual int getage() { return age; }
    void setage(int age)
    {
        this->age = age;
    }
};

class Student : public Person
{
private:
    int id;
    int score;
    virtual int getid() { return id; }
    virtual int getscore() { return score; }

public:
    void set(int age, int id, int score)
    {
        setage(age);
        this->id = id;
        this->score = score;
    }
};

int main()
{
    int n, i; 
    cin >> n;
    Student stu[20];
    int age, idnumber, mark;
    for (i = 0; i < n; ++i)
    {
        cin >> age >> idnumber >> mark;
        stu[i].set(age, idnumber, mark);
    }

    typedef int (*pscore)(Student * st);
    typedef int (*pid)(Student * st);

    void **pvtr = *(void ***)&stu[0];

    int max = -1, temp = -1;
    for (i = 0; i < n; ++i)
    {
        temp = ((pscore)pvtr[2])(&stu[i]);
        if (max < temp)
        {
            max = temp;
        }
    }
    for (i = 0; i < n; ++i)
    {
        if (max == ((pscore)pvtr[2])(&stu[i]))
        {
            cout << stu[i].getage() << " " << ((pid)pvtr[1])(&stu[i]) << " " << max << endl;
            break;
        }
    }
    system("pause");
    return 0;
}
阅读 2.2k
2 个回答

因为没有传this参数啊,而且偏移也不是这么算的,(pscore) * ((int *)*(int *)(&stu[i])+4); 能得到getscore是因为在64位系统上 4*int 刚好是2个指针的长度 所以碰巧对了。

typedef int (*pscore)(Student *st);

void** pvtr = *(void***)&stu[0];
    /*
     * pvtr[0] = getage
     * pvtr[1] = getid
     * pvtr[2] = getscore
     * */
    int max = -1, temp = -1;
    for (int i = 0; i < n; ++i){
        temp = ((pscore)pvtr[2])(&stu[i]);
        if (max < temp)
        {
            max = temp;
        }
    }

不同编译器对c++对象的内存布局一般是各不相同的,你这样写代码要么有非常特殊原因且非常了解编译器,要么不建议。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题