无法将派生类 push_back() 推入 C++ 中的 STL 列表

Posted

技术标签:

【中文标题】无法将派生类 push_back() 推入 C++ 中的 STL 列表【英文标题】:Fail to push_back() derived class into STL list in C++ 【发布时间】:2016-02-08 16:38:03 【问题描述】:

我将不胜感激。

问题是我无法成功将某些东西 push_back 到 STL 列表中。 以下是详细信息:

Fo 是一个抽象类,Foo 是一个继承自 Fo 的类。 f0f1Foo 类的实例。 fooList 的类型为 std::list<Foo>foList 的类型为 std::list<Fo*>

当我尝试fooList.push_back(f1); 时,我可以cout 成员p 的值,但不能调用函数test(); 当我尝试foList.push_back(&f1); 时,我什至无法cout 成员p 的值,更不用说调用函数test()

注释了error-1/2/3的行,我得到了输出:

Fo constructor
Foo constructor
Fo constructor
Foo initialization 
Fo constructor
Foo copy constructor
inside fooList :11
------------------------

我也意识到foList.push_back(&f1) 没有调用Foo 复制构造函数, 这可能与错误 2 有关。

当我尝试在fooList 中调用函数test() 时,我收到错误消息:

error: member function 'test' not viable: 'this' argument has type
  'const Foo', but function is not marked const

当我尝试在foList 中计算成员 p 时,我收到错误消息:

error: no member named 'p' in 'Fo'

我不知道如何解决这个问题。

非常感谢!

完整代码列表如下:

#include <iostream>
#include <list>

class Fo

public:
    Fo()  std::cout << "Fo constructor" << std::endl; 
    Fo(const Fo& f)  std::cout << "Fo copy constructor" << std::endl; 
    virtual ~Fo();
    virtual void test()=0;
;

class Foo : public Fo

public:
    int p;
    Foo()  std::cout << "Foo constructor" << std::endl; 
    Foo(int p_): p(p_) std::cout << "Foo initialization " << std::endl;;
    Foo(const Foo& f)  this->p = f.p; std::cout << "Foo copy constructor" << std::endl; 
    virtual void test() std::cout<<"testing Foo ... "<<std::endl;
;

int main() 
    Foo f0,f1(11);

    std::list<Foo> fooList;
    std::list<Foo>::const_iterator i=fooList.begin();
    fooList.push_back(f1);i++;
    std::cout << "inside fooList :" << i->p << std::endl;
    //std::cout<<"inside fooList :"<<i->p<<" and "<<i->test();  // error-1
    std::cout << "------------------------" << std::endl;

    std::list<Fo*> foList;
    std::list<Fo*>::const_iterator it=foList.begin();
    foList.push_back(&f1);it++;
    //std::cout<<(*it)->p<<std::endl;  // error-2
    //std::cout<<"inside foList :"<<(*it)->p<<" and "<<it->test();  // error-3

    return 0;

【问题讨论】:

简短的回答是,如果要进行推导,则需要存储指针,而不是对象。基础对象的容器只能容纳基础对象,不能容纳派生对象。如果您修复了一些问题以便代码编译,那么您最希望的就是“切片”,这意味着派生对象的实例实际上被转换为基类对象,而那些转换后的基类对象就是存储在您的列表中的对象。 不起作用,因为对象被复制并且容器实际上只存储声明类型的对象。顺便说一句:如果您想在构造函数和析构函数中使用该输出“证明”任何内容,那么您缺少一些,请查看所谓的“三定律”。 我想知道这些错误消息有什么不清楚的地方。他们确切地说出了问题所在。 【参考方案1】:

修复

//std::cout<<"inside fooList :"<<i->p<<" and "<<i->test();  // error-1

改变

std::list<Foo>::const_iterator i=fooList.begin();

std::list<Foo>::iterator i=fooList.begin();

修复

//std::cout<<(*it)->p<<std::endl;  // error-2

替换为

std::cout<<(Foo*(*it))->p<<std::endl;  // error-2

修复:

//std::cout<<"inside foList :"<<(*it)->p<<" and "<<it->test();  // error-3

替换

//std::cout<<"inside foList :"<<(Foo*(*it))->p<<" and "<<it->test();  // error-3

【讨论】:

我明白你对错误 2 的看法。我需要类型转换。但是按照你编译器的方式仍然显示错误消息为 error-1。 您的代码出现更多错误,将 test() 的返回类型从 void 更改为 int )->test() at error-3 现在可以使用了。而且似乎没有必要用迭代器替换 const_iterator。你能告诉我为什么返回类型在这里很重要吗?谢谢。 这是单独问题的主题/ 简而言之,'

以上是关于无法将派生类 push_back() 推入 C++ 中的 STL 列表的主要内容,如果未能解决你的问题,请参考以下文章

c++:向量问题的向量

为啥我无法将对象 push_back 放入 C++ 多维向量中

C++:派生类解构时基类中的字符串参数解构

无法将参数 1 从派生指针转换为基类指针引用

c++ 将指针推入指针优先级队列会导致立即 valgrind 错误

如何从基对象的派生类访问函数