如何将不同的数据类型存储在一个列表中? (C ++) [英] How to store different data types in one list? (C++)

查看:969
本文介绍了如何将不同的数据类型存储在一个列表中? (C ++)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要存储对象的各种属性的列表。属性包含名称和数据,可以是任何数据类型。

I need to store a list of various properties of an object. Property consists of a name and data, which can be of any datatype.

我知道我可以创建一个类Property,并扩展它与不同的PropertySubClasses只有不同

I know I can make a class "Property", and extend it with different PropertySubClasses which only differ with the datatype they are storing, but it does not feel right.

class Property
{
     Property(std::string name);
     virtual ~Property();

     std::string m_name;
};

class PropertyBoolean : Property
{
     PropertyBoolean(std::string name, bool data);

     bool m_data;
};

class PropertyFloat : Property
{
     PropertyFloat(std::string name, float data);

     float m_data;
};

class PropertyVector : Property
{
     PropertyVector(std::string name, std::vector<float> data);

     std::vector<float> m_data;
};

现在我可以将所有类型的属性存储在

Now I can store all kinds of properties in a

 std::vector<Property*>

并且为了获取数据,我可以将对象转换为子类。或者我可以创建一个纯虚函数来处理函数中的数据,而不需要转换。

and to get the data, I can cast the object to the subclass. Or I can make a pure virtual function to do something with the data inside the function without the need of casting.

无论如何,这样做并不能创建这些不同的类型的子类,它们仅根据它们存储的数据类型不同。是否有其他方便的方法来实现类似的行为?

Anyways, this does not feel right to create these different kind of subclasses which only differ by the data type they are storing. Is there any other convenient way to achieve similar behavior?

我没有访问Boost。

I do not have access to Boost.

推荐答案

C ++是一种多范式语言。它发光最亮,是最强大的,其中范例混合。

C++ is a multi-paradigm language. It shines brightest and is most powerful where paradigms are mixed.

class Property
{
public:
    Property(const std::string& name) //note: we don't lightly copy strings in C++
      : m_name(name) {}
    virtual ~Property() {}
private:
    std::string m_name;
};

template< typename T >
class TypedProperty : public Property
{
public:
    TypedProperty (const std::string& name, const T& data)
      : Property(name), m_data(data);
private:
    T m_data;
};

typedef std::vector< std::shared_ptr<Property> > property_list_type;






em> 为什么使用 std :: shared_ptr< Property> 而不是属性*

考虑这个代码:


Why using std::shared_ptr<Property> instead of Property*?
Consider this code:

void f()
{
  std::vector<Property*> my_property_list;
  for(unsigned int u=0; u<10; ++u)
    my_property_list.push_back(new Property(u));

  use_property_list(my_property_list);

  for(std::vector<Property*>::iterator it=my_property_list.begin();
                                      it!=my_property_list.end(); ++it)
    delete *it;
}

for 尝试清理,删除向量中的所有属性,只是在它超出范围,并获取所有的指针。

现在,虽然这可能看起来很好的新手,如果你一个只有轻微经验的C ++开发人员,代码应该在你看到它后立即报警。

That for loop there attempts to cleanup, deleting all the properties in the vector, just before it goes out of scope and takes all the pointers with it.
Now, while this might seem fine for a novice, if you're an only mildly experienced C++ developer, that code should raise alarm bells as soon as you look at it.

问题是调用 use_property_list()可能会抛出异常。如果是这样,函数 f()将立即离开。为了正确清理,将调用 f()中创建的所有自动对象的析构函数。也就是说, my_property_list 将被正确销毁。 std :: vector 的析构函数将会很好地清理它保存的数据。 然而,它拥有指针 ,如何 std :: vector 知道这些指针是否是最后一个指向它们对象?

因为它不知道,它不会删除对象,它只会销毁指针,当它销毁它的内容,留给你的堆上的对象,你没有任何指针。这就是所谓的泄漏。

The problem is that the call to use_property_list() might throw an exception. If so, the function f() will be left right away. In order to properly cleanup, the destructors for all automatic objects created in f() will be called. That is, my_property_list will be properly destroyed. std::vector's destructor will then nicely cleanup the data it holds. However, it holds pointers, and how should std::vector know whether these pointers are the last ones referencing their objects?
Since it doesn't know, it won't delete the objects, it will only destroy the pointers when it destroys its content, leaving you with objects on the heap that you don't have any pointers to anymore. This is what's called a "leak".

为了避免这种情况,您需要捕获所有异常,清除属性,并重新抛出异常。但是,从现在开始,十年后,有人必须为10MLoC应用程序添加一个新功能,并且在匆忙的情况下添加代码,在某些条件成立时,该功能会过早地离开。代码被测试,它的工作原理和不崩溃 - 只有服务器它现在一小时泄漏几个字节,使其崩溃,由于内存大约每周一次。找到可以进行许多小时的正常调试。

In order to avoid that, you would need to catch all exceptions, clean up the properties, and the rethrow the exception. But then, ten years from now, someone has to add a new feature to the 10MLoC application this has grown to, and, being in a hurry, adds code which leaves that function prematurely when some condition holds. The code is tested and it works and doesn't crash - only the server it's part of now leaks a few bytes an hour, making it crash due to being out of memory about once a week. Finding that makes for many hours of fine debugging.

底线:从不手动管理资源,总是将它们包装在一个类的对象中,该类设计为处理这样​​的资源的一个实例。对于动态分配的对象,这些句柄称为智能指针,最常用的是 shared_ptr

Bottom line: Never manage resources manually, always wrap them in objects of a class designed to handle exactly one instance of such a resource. For dynamically allocated objects, those handles are called "smart pointer", and the most used one is shared_ptr.

这篇关于如何将不同的数据类型存储在一个列表中? (C ++)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆