How to store different data types in one list? (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;
Edit: 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;
}
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.
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".
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.
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
.
Is it possible to store multiple data types in an ArrayList using C#?
Yes you can store like this
ArrayList aa = new ArrayList();
aa.Add(false);
aa.Add(1);
aa.Add("Name");
ArrayList belongs to the days that C# didn't have generics. It's deprecated in favor of List. You shouldn't use ArrayList in new code that targets .NET >= 2.0 unless you have to interface with an old API that uses it.
ArrayList vs List<> in C#
How can I make a list of different datatypes then save to a file c#
You could use XML Serialization.
First, create a class to encapsulate your data:
public class Data
{
public string Name;
public int Age;
public string FavoriteColor;
public int FavoriteNumber;
}
Then, an example of writing and reading the file:
static void Main(string[] args)
{
Console.Write("Name:");
string name = Console.ReadLine();
//Get age.
Console.Write("Age:");
int age = Convert.ToInt16(Console.ReadLine());
//Get favorite color.
Console.Write("Favorite color:");
string color = Console.ReadLine();
//Get favorite number.
Console.Write("Favorite number:");
int number = Convert.ToInt16(Console.ReadLine());
//Save to stats.txt
string path = @"C:\Users\max\OneDrive\Desktop\Code\C#\SaveAndLoad\STATS\stats.txt";
Data data = new Data() { Name = name, Age = age, FavoriteColor = color, FavoriteNumber = number };
using (System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.OpenOrCreate))
{
System.Xml.Serialization.XmlSerializer xml = new System.Xml.Serialization.XmlSerializer(data.GetType());
xml.Serialize(fs, data);
}
// read from stats.txt into a Data object
Data data2;
using (System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.Open))
{
System.Xml.Serialization.XmlSerializer xml = new System.Xml.Serialization.XmlSerializer(typeof(Data));
data2 = xml.Deserialize(fs) as Data;
}
// do something with "data2":
Console.WriteLine("Name: " + data2.Name);
Console.WriteLine("Age: " + data2.Age);
Console.WriteLine("Color: " + data2.FavoriteColor);
Console.WriteLine("Number: " + data2.FavoriteNumber);
Console.Write("Press Enter to Quit");
Console.ReadLine();
}
Generated XML File:
<?xml version="1.0"?>
<Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Mike</Name>
<Age>47</Age>
<FavoriteColor>Blue</FavoriteColor>
<FavoriteNumber>42</FavoriteNumber>
</Data>
If you create another class that has List<Data>
in it, you can use very similar code to serialize that class in the same manner.
Related Topics
Delete Pointer to Multidimensional Array in Class Through Another Pointer - How
How to Make an Unordered Set of Pairs of Integers in C++
Benefits and Portability of Boost Library
Comparison of Arrays in Google Test
Why Simple Console App Runs But Dialog Based Does Not Run in Win Ce 6.0
Defining Operator< for a Struct
Does Std::Bind Work with Move-Only Types in General, and Std::Unique_Ptr in Particular
Passing Non-Pod Type to Variadic Function Is Undefined Behavior
Memory Allocation/Deallocation
Symbol Not Found When Using Template Defined in a Library
What's the Difference Between Cstdlib and Stdlib.H
Explicitly Exporting Shared Library Functions in Linux