通过基类指针访问子类的成员函数

use*_*257 3 c++ qt

我正在尝试编写一个使用DOM来编写注册列表的类,以XML格式存档.注册列表包含三种类型的注册Registration,它们是标准的基本注册类GuestRegistration,StudentRegistration它们都来自Registration.

GuestRegistration班级有一个独特的成员category,学生注册有独特的成员qualification.

当我遍历注册指针列表时,我只能访问基类Registration的成员函数.有没有什么办法可以访问子的数据成员使用getter函数getCategorygetQualification?每当类名与两者中的任何一个匹配时,我都尝试创建一个GuestRegistrationStudentRegistration指针,但是得到一个指针转换错误.

void RegistrationListWriter::write(RegistrationList r) {
    QList<Registration*> regList = r.getRegistrationList();

    for (int i = 0; i < regList.size(); ++i) {
        QString cn = regList.at(i)->metaObject()->className();
        Person tempPerson = regList.at(i)->getAttendee();

        appendRegistrationAndType(cn);
        appendAttendee(tempPerson);
        //this is where my issue starts
        if (cn == "GuestRegistration") {
            GuestRegistration guestReg = regList.at(i);
            appendAttendeeCatagory(guestReg.getCatagory());
        }

        if (cn == "StudentRegistration") {
            StudentRegistration* stuReg = regList.at(i);
            appendAttendeeQualification(stuReg->getQualification());
        }

        appendBookingDate(regList.at(i)->getBookingDate().toString());
        appendRegistrationFee(regList.at(i)->calculateFee());

    }
}
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 5

您可以dynamic_cast用来检查特定的子类:

void RegistrationListWriter::write(RegistrationList r) {
    QList<Registration*> regList = r.getRegistrationList();

    for (int i = 0; i < regList.size(); ++i) {
        Registration *reg = regList.at(i);

        appendRegistrationAndType(reg->metaObject()->className());
        appendAttendee(reg->getAttendee());

        if (GuestRegistration *guestReg = dynamic_cast<GuestRegistration*>(reg)) {
            appendAttendeeCatagory(guestReg->getCatagory());
        }
        else
        if (StudentRegistration* stuReg = dynamic_cast<StudentRegistration*>(reg)) {
            appendAttendeeQualification(stuReg->getQualification());
        }
        // and so on ...

        appendBookingDate(reg->getBookingDate().toString());
        appendRegistrationFee(reg->calculateFee());    
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我建议在Registration类本身中实现一个虚方法,子类可以覆盖它以根据需要注册其他项,例如:

class Registration {
    ...
    virtual void appendExtraAttendees(RegistrationListWriter *writer){}
    ...
};
Run Code Online (Sandbox Code Playgroud)

class GuestRegistration : public Registration {
    ...
    virtual void appendExtraAttendees(RegistrationListWriter *writer);
    ...
};

void GuestRegistration::appendExtraAttendees(RegistrationListWriter *writer){
    writer->appendAttendeeCatagory(getCatagory());
}
Run Code Online (Sandbox Code Playgroud)

class StudentRegistration : public Registration {
    ...
    virtual void appendExtraAttendees(RegistrationListWriter *writer);
    ...
};

void StudentRegistration::appendExtraAttendees(RegistrationListWriter *writer){
    writer->appendAttendeeQualification(getQualification());
}
Run Code Online (Sandbox Code Playgroud)

void RegistrationListWriter::write(RegistrationList r) {
    QList<Registration*> regList = r.getRegistrationList();

    for (int i = 0; i < regList.size(); ++i) {
        Registration *reg = regList.at(i);

        appendRegistrationAndType(reg->metaObject()->className());
        appendAttendee(reg->getAttendee());

        reg->appendExtraAttendees(this);

        appendBookingDate(reg->getBookingDate().toString());
        appendRegistrationFee(reg->calculateFee());    
    }
}
Run Code Online (Sandbox Code Playgroud)

或者:

class Registration {
    ...
    virtual void appendAttendees(RegistrationListWriter *writer);
    ...
};

void Registration::appendAttendees(RegistrationListWriter *writer){
    writer->appendAttendee(getAttendee());
}
Run Code Online (Sandbox Code Playgroud)

class GuestRegistration : public Registration {
    ...
    virtual void appendAttendees(RegistrationListWriter *writer);
    ...
};

void GuestRegistration::appendAttendees(RegistrationListWriter *writer){
    Registration::appendAttendees(writer);
    writer->appendAttendeeCatagory(getCatagory());
}
Run Code Online (Sandbox Code Playgroud)

class StudentRegistration : public Registration {
    ...
    virtual void appendAttendees(RegistrationListWriter *writer);
    ...
};

void StudentRegistration::appendAttendees(RegistrationListWriter *writer){
    Registration::appendAttendees(writer);
    writer->appendAttendeeQualification(getQualification());
}
Run Code Online (Sandbox Code Playgroud)

void RegistrationListWriter::write(RegistrationList r) {
    QList<Registration*> regList = r.getRegistrationList();

    for (int i = 0; i < regList.size(); ++i) {
        Registration *reg = regList.at(i);

        appendRegistrationAndType(reg->metaObject()->className());

        reg->appendAttendees(this);

        appendBookingDate(reg->getBookingDate().toString());
        appendRegistrationFee(reg->calculateFee());    
    }
}
Run Code Online (Sandbox Code Playgroud)