从异构 std::list 中检索数据
Retrieve data from heterogeneous std::list
在下面的代码中,我只是尝试尝试使用异构 std::list,其中我在 Base* 类型的列表中存储了三个派生类对象。从列表中检索数据时,我遇到了一些问题。我该怎么做?下面的代码之所以有效,是因为所有三个类在定义上都是相同的。因此,编译器以某种方式设法为我提供了预期的输出。
#include <list>
#include <iostream>
#include <string.h>
class Base;
typedef std::list<Base*> any_list;
class Base{};
class Derived1 : public Base
{
public:
std::string s;
Derived1():s("D1"){}
};
class Derived2 : public Base
{
public:
std::string s;
Derived2():s("D2"){}
};
class Derived3 : public Base
{
public:
std::string s;
Derived3():s("D3"){}
};
int main(int argc, char **argv) {
any_list l;
l.push_back(new Derived1);
l.push_back(new Derived2);
l.push_back(new Derived3);
for(any_list::iterator itr=l.begin();itr!=l.end();++itr)
std::cout<<((Derived1*)*itr)->s;
}
请注意,o/p 是 -
D1 D2 D3
现在,如果我在任何类中添加一个额外的成员,这不起作用(这是预期和正确的(。那么,我应该如何类型转换数据并从异构列表中检索它呢?我在这里错过了什么吗?
最简单的方法可能是像这样定义 Base:
class Base {
public:
virtual const std::string& getData() = 0;
}
然后让各种派生类根据需要实现getData()
。这样,您的输出循环可能就是:
for (Base* b : l) {
cout << b->getData();
}
我会重新定义Base
,以便有一个虚拟方法来输出信息:
class Base {
friend std::ostream & operator << (std::ostream &os, const Base &b) {
b.print(os);
return os;
}
virtual void print (std::ostream &os) const = 0;
public:
virtual ~Base () {}
};
然后,您将被迫在每个派生类中实现一个 print
方法。您的打印循环如下所示:
for (any_list::iterator itr=l.begin();itr!= l.end();++itr)
std::cout << **itr;
您的列表应避免管理裸指针,因为您将自己置于泄漏内存的风险中。您可以改用智能指针:
typedef std::list< std::unique_ptr<Base> > any_list;
由于unique_ptr
需要从指针显式构造,因此需要更新填充列表的代码。
l.push_back(std::unique_ptr<Base>(new Derived1));
l.push_back(std::unique_ptr<Base>(new Derived2));
l.push_back(std::unique_ptr<Base>(new Derived3));
你的演员(Derived1*)*itr
相当于一个static_cast
,上面写着:
如果 prvalue 的类型 "指向 cv1
B
的指针" 指向一个实际上是类型D
对象的子对象的子对象的B
,则生成的指针指向类型D
的封闭对象。否则,转换的结果是未定义的。
因此,您具有未定义的行为,因为您正在投射指向Derived2
的指针,并将对象Derived3
到Derived1*
。
实现此目的的正确方法是在Base
中定义std::string s;
,并为其提供一个接受std::string
参数的构造函数。然后,可以使 Derived1
的构造函数Derived3
使用适当的字符串参数调用此构造函数。
如果将任何额外的成员添加到其中一个Derived
类,则无法通过多态Base*
访问它们。然而,试图这样做是设计不好的标志。您应该只将Base*
指向的对象视为Base
对象。也就是说,Base
描述了这些对象的接口。
如果你真的需要做一些特定于指向Base*
对象的派生类的事情,你可以使用dynamic_cast
:
if (Derived1* p = dynamic_cast<Derived1*>(*itr)) {
// This condition will only be true if the object pointed to by `*itr` really is a Derived1
}
#include <list>
#include <vector>
#include <iostream>
#include <string.h>
class Base;
typedef std::list<Base*> any_list;
class Base{
public:
virtual ~Base(){}
virtual std::string getData()=0;
};
class Derived1 : public Base
{
public:
std::string s;
Derived1():s("D1"){}
std::string getData()
{
return s;
}
};
class Derived2 : public Base
{
public:
std::string s;
Derived2():s("D2"){}
std::string getData()
{
return s;
}
};
class Derived3 : public Base
{
public:
std::string s;
Derived3():s("D3"){}
std::string getData()
{
return s;
}
};
int main(int argc, char **argv) {
any_list l;
l.push_back(new Derived1);
l.push_back(new Derived2);
l.push_back(new Derived3);
for(any_list::iterator itr=l.begin();itr!=l.end();++itr)
std::cout<<((Base*)*itr)->getData()<<std::endl;
}
感谢您的帮助。混乱是明确的,问题就解决了。顺便说一下,什么是——
typedef std::list<std::unique_ptr> any_list;
我在命名空间中没有找到任何名为unique_ptr
std::
的东西。 :(
- 通过 host() 从 af::array 检索数据会导致错误的数据
- 无法从 SQL Server 检索数据
- sd_journal_send发送二进制数据.如何使用日志检索数据?
- 在 c++ 中使用指向对象的指针检索数据
- 从新实例的向量中检索数据返回 0
- 如何通过串行终端检索数据而不破坏其在 GNU ARM 嵌入式中的基本值?
- QNETWORK停止连接并检索数据
- 如何在 c++ 中从文件中检索数据
- 如何从 linux 二进制文件中存储和检索数据
- ifstream不使用C 中的数组检索数据
- 无法从数组二次表达式中检索数据值
- 从具有多态性的类中检索数据
- 当我将字符串数组从 VBA 传递到 c++ 并将它们用作映射中的键时,为什么我无法从映射中检索数据(使用键)
- 调用readAll()后,不再无法从QIODevices检索数据.缓冲区已冲洗
- glBufferStorage + glGetBufferSubData 用于检索数据
- 如果没有数据,则创建一个包含数据的文本文件,然后读取它以检索数据
- 通过HTTP请求从站点检索数据(使用QT5.4的C++)
- 通过传递一个ID(c++)从数据库中检索数据
- 如何从专用字符串中检索数据
- 使用 QNetworkAccessManager 从 web 检索数据:文件已下载,但 QNetworkReply::r