Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing sub class's member functions through base class pointer

Tags:

c++

qt

I am trying to write a class that uses DOM to write a list of Registrations to file as XML. The list of registrations contains three types of registration Registration which is the standard base registration class GuestRegistration and StudentRegistration which both derive from Registration.

The GuestRegistration class has a unique member category and the student registration has unique member qualification.

When I iterate over the list of registration pointers I only have access to the base class Registration's member functions. Is there any way I can access the subclasses' data members to use the getter functions getCategory and getQualification? I've tried creating a GuestRegistration and StudentRegistration pointer whenever the class name matches either of the two, but get a pointer conversion error.

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

    }
}
like image 800
user2094257 Avatar asked Jan 26 '26 17:01

user2094257


1 Answers

You can use dynamic_cast to check for specific sub-classes:

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

However, I would suggest implementing a virtual method in the Registration class itself that your sub-classes can override to register additional items as needed, eg:

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

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

void GuestRegistration::appendExtraAttendees(RegistrationListWriter *writer){
    writer->appendAttendeeCatagory(getCatagory());
}

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

void StudentRegistration::appendExtraAttendees(RegistrationListWriter *writer){
    writer->appendAttendeeQualification(getQualification());
}

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

Alternatively:

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

void Registration::appendAttendees(RegistrationListWriter *writer){
    writer->appendAttendee(getAttendee());
}

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

void GuestRegistration::appendAttendees(RegistrationListWriter *writer){
    Registration::appendAttendees(writer);
    writer->appendAttendeeCatagory(getCatagory());
}

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

void StudentRegistration::appendAttendees(RegistrationListWriter *writer){
    Registration::appendAttendees(writer);
    writer->appendAttendeeQualification(getQualification());
}

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());    
    }
}
like image 57
Remy Lebeau Avatar answered Jan 28 '26 08:01

Remy Lebeau



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!