从超类指针C ++访问子类成员

时间:2010-04-01 10:59:40

标签: c++ inheritance virtual-functions dynamic-cast static-cast

我有一组自定义类的Student对象。 CourseStudent和ResearchStudent都继承自Student,而Student的所有实例都是其中一个。

我有一个函数来遍历数组,确定每个Student的子类型,然后在它们上调用特定于子类型的成员函数。

问题是,因为这些函数没有重载,所以在Student中找不到它们,所以编译器会大惊小怪。

如果我有一个指向学生的指针,有没有办法获得指向该学生的子类型的指针?我是否需要在此处进行某种假冒操作以解决编译时错误?

5 个答案:

答案 0 :(得分:10)

最好的方法是使用虚拟功能:

class Student
{
   // ...
   virtual void SpecificFunction() = 0; /* = 0 means it's abstract; it must be implemented by a subclass */
   // ...
};

class CourseStudent
{
    void SpecificFunction() { ... }
};

然后你可以这样做:

Student *student;
student->SpecificFunction();

更糟糕的替代方案可能是使用dynamic_cast

Student *student;
CourseStudent *cs = dynamic_cast<CourseStudent *>(student);

if (cs) {
   /* student is a CourseStudent.. */
   cs->SpecificFunction();
}

答案 1 :(得分:6)

你需要动态演员:

Student * s = new ...;    // create student of some sort

if ( ResearchStudent * r = dynamic_cast<ReasearchStudent*>( s ) ) {
   r->ResFunc();
}
else if ( CourseStudent * c = dynamic_cast<CourseStudent*>( s ) ) {
   c->CourseFiunc();
}
else {
   throw "unknown student type";
}

请注意,这使用了编译器维护的类型信息,前提是该类至少有一个虚函数 - 如果所有其他都失败,则使析构函数成为虚拟(因为它必须在这种情况下仍然是)。您应该始终更喜欢这种方法来维护自己的类型信息。

答案 2 :(得分:3)

虚拟函数在这里是不合适的,因为子类成员函数特定于那些子类(例如,CourseStudent有一个单元列表,而ResearchStudent没有,所以ResearchStudent中的getUnits()函数实现完全没有意义)

我对动态和静态强制转换(cplusplus.com typecasting)进行了一些阅读,在这种情况下,我认为静态强制转换更合适。

static_cast的一般缺点是它不会在运行时执行任何检查,以确保转换为子类型的对象实际上是该子类型而不是其他类型。在这种情况下,我在执行类型之前专门检查类型(使用在子类构造函数中设置的私有数据成员并且没有mutator),所以只要我的检查是好的,静态强制转换应该没有问题。静态强制转换更有效,因为动态强制转换需要更多的运行时资源来执行类型检查。

如果某个成员有可能不是预期类型,静态强制转换就不合适了,所以我会选择动态转换(这是一个赋值,所以一旦提交,代码就不需要维护了,所以以后没有人搞乱它的风险。)

答案 3 :(得分:2)

这几乎可以肯定是在基类中使用纯虚拟成员函数,然后覆盖执行实际工作的派生类。

答案 4 :(得分:1)

您需要static_cast。由于这些函数不是基类的虚拟成员,因此无法通过指向基类的指针调用它们。您需要显式转换为对象的实际类型。

这个问题通常最好通过虚函数解决 - 你不再需要在代码中进行对象类型检查,代码更少,错误更少。