无法将派生类 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
的类。
f0
、f1
是 Foo
类的实例。
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 列表的主要内容,如果未能解决你的问题,请参考以下文章
为啥我无法将对象 push_back 放入 C++ 多维向量中