我正在尝试编写一个使用DOM编写注册列表的类,以XML格式编写文件。注册列表包含三种类型的注册Registration
,它是标准基本注册类GuestRegistration
和StudentRegistration
,它们都来自Registration
。
GuestRegistration
班级有一个独特的成员category
,学生注册有唯一成员qualification
。
当我遍历注册指针列表时,我只能访问基类Registration
的成员函数。有没有办法可以访问子类的数据成员来使用getter函数getCategory
和getQualification
?我曾尝试在类名与两者中的任何一个匹配时创建GuestRegistration
和StudentRegistration
指针,但会得到指针转换错误。
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());
}
}
答案 0 :(得分: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());
}
}
但是,我建议在Registration
类本身中实现一个虚方法,子类可以覆盖它以根据需要注册其他项,例如:
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());
}
}
可替换地:
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());
}
}
答案 1 :(得分:2)
简单的C ++工具是dynamic_cast&lt;&gt;()。
一般来说,最初设计一个需要这种演员表的项目并不是一个好习惯。可以考虑各种设计模式。
我发现您使用的是metaObject()
,因此这意味着Registration
将QObject
作为基类。在这种情况下,可以使用qobject_cast
:
qobject_cast()函数的行为与标准C ++类似 dynamic_cast(),具有不需要RTTI的优点 支持,它适用于动态库边界。
答案 2 :(得分:1)
您可以让基类提供派生类用于编写类特定数据的接口,而不是使用dynamic_cast
。
答案 3 :(得分:0)
可能你需要让这些方法成为虚拟的。 非虚方法使用编译时使用的类的方法,而是在运行时选择子类的虚方法。