【问题标题】:Mixing abstract classes and templates, a recipe for disaster?混合抽象类和模板,灾难的秘诀?
【发布时间】:2011-07-23 15:57:52
【问题描述】:

我遇到了以下情况。我有三个班级参与了这个混淆。 ListListNodeCity。我有一个List<City *>,列表将由一组ListNode<City *>(列表节点周围的标准包装器)组成。

City 是一个抽象类,因此有几个继承自它的类可以放在这个列表中并以多态方式访问。 List 类有一个getHead() 方法,它返回一个指向ListNode 的指针,即头部。

任何城市都有人口,因此要访问人口,我希望以下内容可以工作。不是,因此我的问题。我把它分解成几块,以使其更简单:

    ListNode<City *> *head= country->city_list->getHead();
    City *headnode = *head->getNode();

    cout << "Test: " << headnode->getPopulation() << endl;

getPopulation() 返回一个整数。 country 定义为 List&lt;City*&gt; *city; 任何有关如何解决我的问题的帮助将不胜感激。

edit 添加更多代码以更好地了解我正在使用的内容。一、ListNode:

template <class T>
class ListNode
{
public:
    ListNode() {next = 0;node = 0;};

    ListNode(T *t) {node = t; next = 0;};

    ListNode(const ListNode &l)
    {
        //long copy constructor. snip.
    };

    T *getNode() const { return node; }
    ListNode *getNext() const { return next; };

private:
    T *node;
    ListNode *next;
};

现在,这是 List 类中可能相关的内容。

template <class T>
class List
{
public:
    List()
    {
        head = 0;
        size = 0;
    };

    List(ListNode<T> *t)
    {
        head = t;
        size = 1;
    };

    List(T *t)
    {
        head = new ListNode<T>(t);
        size = 1;
    };

    List(const List<T> &t)
    {
        // long copy constructor. snip.
    };
    //bunch of irrelevent methods.


    ListNode<T> *getHead() const {return head;};

    List &operator+=(T &t)
    {
        this->insert(&t);
        size++;
        return (*this);
    };


private:
    List &insert(T *t)
    {
        ListNode<T> *current = head;
        if (current == 0)
        {
            head = new ListNode<T>(t);
        }
        else
        {
            while (current->getNext() != 0)
            {
                current = current->getNext();
            }
            current->setNext(new ListNode<T>(t));
        }
        return (*this);
    };

    ListNode<T> *head;
    int size;
};

我有一种预感,插入过程可能是问题所在。我使用 List 类的 += 运算符插入,如上面的 List 实现所示。它也调用上面显示的私有插入方法。它看起来像这样: 城市 *somecity = new City(x,y,z); //一些参数。整数。 *city_list += 某个城市; // 其中 city_list 是一个列表。

【问题讨论】:

  • 我能想到实现自己的List 而不是使用std::list 的唯一原因是功课。如果是这种情况,请添加作业标签。如果没有,请认真考虑是否不能简单地使用std::liststd::vector
  • 但是......实际上什么不起作用?你得到什么错误? blah 是什么?
  • @Space_C0wb0y - 不是合法的家庭作业。至少不是学校作业。过去 2 天左右,我一直在尝试更新我的 C++,并且我将这些示例用作学习工具。话虽如此,请随意对待它,就像对待任何其他家庭作业一样,因为这是我学习的最佳方式
  • 我得到的错误是在运行时。 “ refresher.exe 中 0x01087a30 处未处理的异常:0xC0000005:访问冲突读取位置 0x4589009b。”
  • 它会工作得很好。 City 只是一个模板参数。您在代码中的任何地方都使用T*,因此无论如何访问时都会以City* 结束。这就是你想要的。

标签: c++ templates inheritance


【解决方案1】:

好吧,你可以做的是:

ListNode<City *>* head = new ListNode<City*>(country->city_list->getHead());
City* headnode = head->getNode();

cout << "Test: " << headnode->getPopulation() << endl;

它将现有的City(在内存上)放在List节点的头部,以此类推。

如果你想复制它们,也许你可以这样做:

ListNode<City *>* head = new ListNode<City*>*(new City(country->city_list->getHead()));
City* headnode = new City(head->getNode());

cout << "Test: " << headnode->getPopulation() << endl;

希望对你有所帮助。

【讨论】:

    【解决方案2】:

    我认为您遇到了变量范围问题。

    您的ListNode 类包含指向节点值的指针。您的ListNode 构造函数接收指向节点值的指针并保存它。

    问题是,如果该指针指向一个超出范围的局部变量。您的ListNode 的节点指针现在指向一个不存在的对象。例如在这个例子中

    addToList(List<int>& myList)
    {
        int x = 3;
        myList += x;  // pointer to x is in the list
    }
    // Out of scope; x no longer exists, but myList has a pointer to it.
    // Accessing this node will result in an error.
    

    有几种可能的补救措施:

    1. 让您的ListNode 包含值而不是指针。这里的缺点是您将复制这些值
    2. 使用将管理对象生命周期的引用计数智能指针实现ListNode

    【讨论】:

    • 如果我总是在堆上分配,这是一个问题吗?我想如果您从不将局部变量添加到列表中,应该没问题吗?还是有更深层次的问题?
    • 如果你一直在使用堆,只有当指针被删除时你才会遇到麻烦。所以这可能不是问题,但它仍然是类设计的问题,因为它很容易被错误地使用。
    猜你喜欢
    • 1970-01-01
    • 2015-11-18
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 2019-12-15
    • 2019-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多