【问题标题】:Linked list of different classes, how to access specific class functions with pointer?不同类的链表,如何用指针访问特定的类函数?
【发布时间】:2015-05-10 15:42:47
【问题描述】:

好的,我有一个人员链接列表。但是,我可以将人员、员工、教员或学生添加到列表中,因为其他 3 个是子类。

教师指导:“添加子菜单项和相关功能(插入书),允许将新书添加到现有学生节点的书树中。新书必须插入正确的位置以维护二叉搜索树特性。必须输入学生姓名、书名、url等信息。为了简化程序,可以假设链表中的所有节点都是学生节点。

^^ ** 我想指出我看到她所说的简化假设所有链表都是学生节点,但是 Personnel/Employee/Faculty 和链表的所有代码都在作业中提供。所以,我能想到的“使用”的唯一方法是浏览所有代码,将任何从 Personnel 到 Student 的引用更改为任何引用,但这在那时似乎是一个相当愚蠢的任务......

所以我的问题是:我需要遍历链表,直到找到仅使用名称字段的正确条目。但随后我需要编辑与该条目相关联的 BookTree 类,该条目只有子类 Student 具有。由于类型与人员不匹配,我无法使用学生指针遍历链接列表(尽管列表中除了学生之外的任何内容都是空的),但是如果我使用人员指针找到它,我当然会赢'无权访问学生特定的功能来编辑我需要的内容。

我试过 Student *ptr = &PersonnelPtr 只是在找到正确的地址后为其分配地址,没有骰子。

代码:

int add_book()
{
    char studentName[50]; // blah
    PersonnelNode *temp, *prev;
    Student *student;       
    temp = head;
    prev = temp;
    while (temp != NULL)
    {
        student = temp->getNode(); // this line gives "value of type Personnel* cannot be assigned to an entity of type Student*
        if (_stricmp(studentName, student->getName()) != 0) 
        {
            prev = temp; // loop through
            temp = temp->getNext();
            index++;
        }
        else
        {
            // Do Stuff
            // More importantly in the do stuff part I need access to Student-specific data/functions that Personnel pointer won't see

【问题讨论】:

  • Personel 派生自Student?如果是,它们是否通过虚函数实现了一个通用接口?
  • Personnel 是父级。人事 > 员工 > 教职员工 > 学生
  • 看来你必须投:( Student* student = dynamic_cast<Student*>(tempNode);
  • 但是后来当我需要向学生添加书籍时,人员指针会出错。所以我不确定如何使用它。但是我认为我可以用任何一种方式解决虚函数的问题,几乎完成了尝试
  • 是的,这似乎有效,谢谢@vsoftco 我不知道如何将其标记为已回答,可能是因为您刚刚在评论中回答了大声笑

标签: c++ inheritance linked-list


【解决方案1】:

您应该使用指向Personnel 的指针来控制其他实体(子实体)。现在你正在做相反的事情,编译器告诉你右手边(Personnel*)不能转换为Student*。那是因为向下转换是不可能隐式的。通常,DerivedBase,因此您可以从Derived* 隐式转换为Base*(向上转换),但不能反过来。

参见例如this tutorial 了解更多关于向上/向下转换的信息。

编辑如果您知道Personel* 指针指向Student,那么您可以使用dynamic_cast<Student*>(your_pointer) 访问对象的Student 功能。但是,铸型通常是设计不完美的标志,您应该尽量避免它们。特别是,您如何知道列表中对象的动态类型是什么(假设您的列表已经被其他函数填充)?您可以使用 RTTI(测试 typeid 结果然后 dynamic_cast-ing),但这不仅很痛苦,而且不推荐。最好实现一个通用的虚接口,让编译器在运行时处理选择正确的虚函数。

【讨论】:

  • 虚拟函数(可能是,它仍然是皮塔饼)是更好的答案。这个答案是不够的,因为 Personnel *ptr 将没有为 ptr->setBook(); 定义的函数;当我需要它的时候。它需要成为学生才能使该功能的整个功能起作用。但它不能是一个学生循环遍历链表。
  • 然后确保对象确实是Student (Personnel* p = new Student),并在需要Studentp 功能时使用dynamic_cast<Student*>(p)。但是,演员表的使用在大多数情况下意味着设计问题。你应该尽量避免强制转换,除非真的有必要。所以试着想一些常见的功能并实现一个虚拟接口。如果没有太多共同点,你真的应该考虑一下你是否想要StudentPersonel的孩子。
  • 结论:你真的想要一个有多种动态类型的列表,你可以从中选择不常用的函数吗?我建议不要,请参阅编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多