C ++创建多个派生类的数组

时间:2013-02-14 10:22:19

标签: c++

我有一个基类Student(),有两个派生类GradStudent()和UndergradStudent()。

基类有一个名为getInfo()的函数,这两个派生类有自己的getInfo()函数。

分配是创建一个学生数组并存储该数组中每个类的对象。然后我从每个调用getInfo()(使用每个的基类函数的版本),然后从两个派生类调用getInfo()函数。

对于我的生活,我无法弄清楚如何做到这一点。这是我到目前为止所做的:

(我想我应该在这里提一下,我不能修改基类)

    Student *classRoom[3];

    Student base ( "Jim", "Bean", 1111 );
    classRoom[0] = &base;

    GradStudent test ( "Jack", "Daniels", 1234, 'M', "Art" );
    classRoom[1] = &test;

    UndergradStudent ust1 ( "Johnny", "Walker", 1235, 1 );
    classRoom[2] = &ust1;

    cout << classRoom[1]->getInfo();

有人能指出我正确的方向吗?我会说具体的指令必须是一个数组,所以没有矢量解决方案请(仍然不熟悉它们)。

3 个答案:

答案 0 :(得分:2)

如果你甚至无法修改派生类,就很难调用GetInfo而不知道它们是特定类型的。也许您需要使用直接解决方案:

GradStudent gradStudent;
cout << gradStudent.GetInfo();

或者您可以尝试检查,如果学生是指定派生类,但IMO非常丑陋和危险(在扩展代码方面):

for (int i = 0; i < 3; i++)
{
    GradStudent * gs = dynamic_cast<GradStudent *>(classRoom[i]);
    if (gs != nullptr)
        cout << gs->GetInfo();
    else
    {
        UndergradStudent * ugs = dynamic_cast<UndergradStudent *>(classRoom[i]);
        if (ugs != nullptr)
            cout << ugs->GetInfo();
        else
            cout << classRoom[i]->GetInfo();
    }
}

我不得不说,多态性是专门为处理这样​​的情况而创建的,并且GetInfo在基类中不是虚拟的是严重的架构缺陷。

此外:如果您正在使用指针,请避免将地址检索到本地变量。这可能很危险。而是手动分配和释放内存:

classRoom[0] = new Student;
classRoom[1] = new GradStudent;
classRoom[2] = new UndergradStudent;

// Process data

for (int i = 0; i < 3; i++)
    delete classRoom[i];

边缘:我讨厌以下任务:X不使用Y(其中Y 专门设计用于解决X)。


编辑 :(回应评论)

你问,虚拟功能如何解决问题。假设片刻Student::GetInfo是虚拟的。让我们分析以下几段代码:

Student * student = new Student;
student->GetInfo(); // Student::GetInfo is called

GradStudent * gradStudent = new GradStudent;
gradStudent->GetInfo(); // GradStudent::GetInfo is called

现在没什么好吃的。

Student * student = new GradStudent;
student->GetInfo();
// if Student::GetInfo is virtual, GradStudent::GetInfo is called here
// if Student::GetInfo is not virtual, Student::GetInfo is called here

现在仔细阅读。如果Student::GetInfo 是虚拟的并且在GradStudent类中实现,则GradStudent::GetInfo将被调用,尽管事实上它会在Student变量上调用。 但是,如果Student::GetInfo 不是虚拟,则在以前的情况下,将调用Student::GetInfo。这基本上就是虚函数的工作原理。

在您的情况下,您有一系列Student *变量 - 您不确切知道它们是StudentGradStudent还是UndergradStudent。由于您的Student::GetInfo不是虚拟的,因此对这些变量调用此方法将始终调用Student::GetInfo,无论其实际类型如何。

在这种情况下,我能想到的唯一解决方案是尝试猜测,实际上它们是哪个类:

Student * student = new UndergradStudent;

Student * s = student; // Ok
GradStudent * gs = dynamic_cast<GradStudent *>(student); // Not true, will return NULL/nullptr
UndergradStudent * ugs = dynamic_cast<UndergradStudent *>(student); // Ok

这样您就可以返回原始类型并调用实际变量类型的GetInfo

但请注意,这是一个丑陋的解决方案,虚拟功能可以解决这类问题。

C++ FAQ是进一步了解虚拟功能的好地方。

答案 1 :(得分:0)

如果getInfo()成员函数不是虚拟的,则作业的第一部分是迭代您的数组并在每个实例上调用getInfo()

对于第二部分,您必须将派生类的实例向下转换为它们的实际类型,以便调用派生类的实际成员函数。

另外,我建议您按以下方式填充阵列:

classRoom[0] = new Student( "Jim", "Bean", 1111 );
classRoom[1] = new GradStudent( "Jack", "Daniels", 1234, 'M', "Art" );
classRoom[2] = new UndergradStudent ( "Johnny", "Walker", 1235, 1 );

不要忘记在程序结束时删除它们。

答案 2 :(得分:0)

我对这个问题感到有些困惑,但这是我从中得到的:

遍历classRoom中的每个元素,在每个元素上调用getInfo()。然后输出test.getInfo()ust1.getInfo()的结果。

如果这是正确的,我认为教师可能试图指出的是,如果调用getInfo()的对象是派生类类型之一(GradStudent或{ {1}}),即使指向对象的指针属于UndergradStudent类型,也始终会调用Student*的派生类版本。

这是因为即使您在getInfo()上调用getInfo()Student*也会在运行时绑定到派生类实现(因为getInfo()是虚拟的)