Think about it lately ~It's always been writing templates to make data structures that don't really store any data type. With auto, you need to initialize the type first, so you can start implementing your own implementation that supports storing all data types (including classes or structures you create).
The design was meant to mimic the auto form (what type is passed in and what type is used), which is really simpler but less practical.Later, consider adding Format formatting input strings and any type conversions to CString (excluding the classes you created, of course, because they are not in one form), including the conversion from char(1 byte) to long long(8 bytes), and so on...First of all, show the usage under...
Testauto testte;//This is the name of the class and the class object, which is shown below testte = /*(char*)*/"-1234567890";//A constant string was passed in, but we used the copy form to copy the string memory (content) into our object short testchar1234 = testte.OutShort();//Here we do the string conversion to short type output, where the maximum shorts are stored (we only need part of 32767 to make sure the data is correct. Sometimes it makes sense that we only need so many numbers to do so). testte = /*(int)*/-123456789;//The type of the preceding comment can be self-explanatory and the default system will automatically determine the type (or good ````) based on the byte length (for example, 32000 numbers between 1 and 2 bytes, the default call to the 2-byte method) testte.Format("%s%d!","123",456);//This uses the CStirng style to add the Format method to store data as strings, which is not too boring to use and can save some CString /********************************************************* After introducing this structure, the storage of custom classes ~~~ **********************************************************/
Briefly introduce a small part of the usage, the following describes the structure design:
1. To ensure maximum support for data types and self-defined classes, use the Void* type as the data storage object (this design is similar to a container, which can be called a container, but not as flexible as auto through code, but much more powerful than auto);
2. To better understand what type was passed in and to save time (when passing in your own defined class, use the designed macro call to ensure the correct type) an operator method was made for each data type (float,double does not make a special operator, I rarely use floating point number /.);
3. For the output string (which can be converted from an incoming number to a string for output), a void* type object is defined to make a copy of the data storage object so that the data storage object is not modified;
4. Specific instructions for void operators: Void operators were originally designed to pass in classes defined by themselves and store class objects. Later, it was found that a class object converted to a data type is also a result (such as receiving a void class object converted to a char object to get a byte, getting four pointer bytes) such as losing data!Later, thinking about Java reflection led to the idea that although we can't use Java as well, we can pass parameters through class objects or class names...Thus, custom class object storage is implemented.
5. For the custom class object, I use a method that can directly modify the parameters within the object (considering that template classes written before can directly modify the internal data);
6. Regarding memory management, the classic STL series of ideas has been continued, such as allocating as much memory as you need, releasing excess memory in time, leaving as little fragmentation as possible, and using the same style of destructor to use fiction and make the last memory judgment.
Following is the highlighted implementation section, followed by the full code:
1. Let's start with Custom Class Object Inbound Macro: The first parameter is the Testauto class object, The second parameter is the custom class object (referred to here as the Test1 class), The third parameter is the custom class name or the custom class object. Here is the macro prototype #define WriteType(obj,class_obj,class_name)\ obj.InClassObj(class_obj,sizeof(class_name)); Use reference: Pass in custom class name method WriteType (testte, &testtest12, Test1); Pass in custom class object way WriteType (testte, &testtest12, testtesttest12); 2. enum structure is used inside the class for data type storage: enum { type_int8 //char ,type_uint8 // unsigned char ,type_int16 // short ,type_uint16 // unsigned short ,type_int32 // int ,type_uint32 //unsigned int ,type_int64 // long long ,type_uint64 // unsigned long long ,type_string // char* , type_obj //Custom class object }; 3. Operator methods are used within the class for data type reception: void* operator = (const void* obj); 4. Get custom class objects: void* GetObj() { return m_data; } Custom class objects are acquired through the GetObj() method, which can be passed in as memory addresses directly to the custom class, or the data within the object can be modified directly. Use reference: Data form parameter Test1 test2 = *(Test1*)testte.GetObj(); The memory address Test1* test2 = (Test1*)testte.GetObj() is passed as a pointer; Call memory variable ((Test1*) testte.GetObj()) - >nNum = 5 as a pointer;Paste all the code below:
/* ****************************************************** *Kun-Yu Lee *[email protected] ****************************************************** */ #define WriteType(obj,class_obj,class_name)\Class object saves call macro obj.InClassObj(class_obj,sizeof(class_name)); class Testauto//Reference class implementation { enum { type_int8 ,type_uint8 ,type_int16 ,type_uint16 ,type_int32 ,type_uint32 ,type_int64 ,type_uint64 ,type_string ,type_obj }; public: virtual ~Testauto()//Fictitious destructor for last memory judgement and processing { if (0 != m_data && 0 != m_ndataSize) { delete[] m_data; } if (0 != m_Condata && 0 != m_nCondataSize) { delete[] m_Condata; } } Testauto():m_ntype(0),m_data(0),m_ndataSize(0),m_Condata(0),m_nCondataSize(0)//Do the most basic constructor { } void* InClassObj(const void* obj,int nlen);/* This is used instead of a template to store your own written class objects */ void* operator = (const void* obj);/* Hardly working */ char operator = (const char & obj); unsigned char operator = (const unsigned char & obj); short operator = (const short & obj); unsigned short operator = (const unsigned short & obj); int operator = (const int & obj); unsigned int operator = (const unsigned int & obj); long long operator = (const long long & obj); unsigned long long operator = (const unsigned long long & obj); char* operator = (const char* obj); void* GetObj()//Get custom class object { return m_data; } char OutChar()//Output char is one byte (ascll 10 digit) { if (0 != m_data && 0 != m_ndataSize) { return *static_cast<char*>(m_data); } return NULL; } unsigned char OutUChar()//Output unsigned char one byte (ascll 10 digit) { if (0 != m_data && 0 != m_ndataSize) { return *static_cast<unsigned char*>(m_data); } return NULL; } short OutShort()//Output short { return *static_cast<short*>(GetData(type_int16)); } unsigned short OutUShort()//Output unsigned short { return *static_cast<unsigned short*>(GetData(type_uint16)); } int OutInt()//Output int { return *static_cast<int*>(GetData(type_int32)); } unsigned int OutUInt()//Output unsigned int { return *static_cast<unsigned int*>(GetData(type_uint32)); } long long OutInt64()//Output long long { return *static_cast<long long*>(GetData(type_int64)); } unsigned long long OutUInt64()//Output unsigned long long { return *static_cast<unsigned long long*>(GetData(type_uint64)); } void* GetData(int type);//Get the data type you want to output (most of the data types are encapsulated here) char* Outstring();//Output string int Format(const char *fmt, ...);//Format input string private: int m_ntype;//Storage data type void* m_data;//Store Data Object int m_ndataSize;//Data object size in bytes void* m_Condata;//Store output string address int m_nCondataSize;//String memory size }; inline void* Testauto::InClassObj(const void* obj,int nlen)/* This is used instead of a template to store your own written class objects */ { int nLen = nlen; if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = nLen; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != nLen) { m_ndataSize = nLen; delete[] m_data; m_data = ::operator new(m_ndataSize); } memcpy(m_data,obj,nLen); m_ntype = type_obj; return m_data; } inline void* Testauto::operator = (const void* obj)/* */ { int nLen = sizeof(static_cast<const char*>(obj)); if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = nLen; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != nLen) { m_ndataSize = nLen; delete[] m_data; m_data = ::operator new(m_ndataSize); } memcpy(m_data,obj,nLen); char* data = (char*)obj; m_data = data; return m_data; } inline char Testauto::operator = (const char & obj) { //definetype(char,m_data); int nLen = sizeof(char); if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = nLen; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != nLen) { m_ndataSize = nLen; delete[] m_data; m_data = ::operator new(m_ndataSize); } *static_cast<char*>(m_data) = obj; m_ntype = type_int8; return *static_cast<char*>(m_data); } inline unsigned char Testauto::operator = (const unsigned char & obj) { //definetype(char,m_data); int nLen = sizeof(unsigned char); if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = nLen; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != nLen) { m_ndataSize = nLen; delete[] m_data; m_data = ::operator new(m_ndataSize); } *static_cast<unsigned char*>(m_data) = obj; m_ntype = type_uint8; return *static_cast<unsigned char*>(m_data); } inline short Testauto::operator = (const short & obj) { int nLen = sizeof(short); if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = nLen; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != nLen) { m_ndataSize = nLen; delete[] m_data; m_data = ::operator new(m_ndataSize); } *static_cast<short*>(m_data) = obj; m_ntype = type_int16; return *static_cast<short*>(m_data); } inline unsigned short Testauto::operator = (const unsigned short & obj) { //definetype(char,m_data); int nLen = sizeof(unsigned short); if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = nLen; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != nLen) { m_ndataSize = nLen; delete[] m_data; m_data = ::operator new(m_ndataSize); } *static_cast<unsigned short*>(m_data) = obj; m_ntype = type_uint16; return *static_cast<unsigned short*>(m_data); } inline int Testauto::operator = (const int & obj) { //definetype(char,m_data); int nLen = sizeof(int); if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = nLen; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != nLen) { m_ndataSize = nLen; delete[] m_data; m_data = ::operator new(m_ndataSize); } *static_cast<int*>(m_data) = obj; m_ntype = type_int32; return *static_cast<int*>(m_data); } inline unsigned int Testauto::operator = (const unsigned int & obj) { //definetype(char,m_data); int nLen = sizeof(unsigned int); if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = nLen; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != nLen) { m_ndataSize = nLen; delete[] m_data; m_data = ::operator new(m_ndataSize); } *static_cast<unsigned int*>(m_data) = obj; m_ntype = type_uint32; return *static_cast<unsigned int*>(m_data); } inline long long Testauto::operator = (const long long & obj) { //definetype(char,m_data); int nLen = sizeof(long long); if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = nLen; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != nLen) { m_ndataSize = nLen; delete[] m_data; m_data = ::operator new(m_ndataSize); } *static_cast<long long*>(m_data) = obj; m_ntype = type_int64; return *static_cast<long long*>(m_data); } inline unsigned long long Testauto::operator = (const unsigned long long & obj) { //definetype(char,m_data); int nLen = sizeof(unsigned long long); if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = nLen; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != nLen) { m_ndataSize = nLen; delete[] m_data; m_data = ::operator new(m_ndataSize); } *static_cast<unsigned long long*>(m_data) = obj; m_ntype = type_uint64; return *static_cast<unsigned long long*>(m_data); } inline char* Testauto::operator = (const char* obj) { int nLen = strlen(obj); if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = nLen; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != nLen) { m_ndataSize = nLen; delete[] m_data; m_data = ::operator new(m_ndataSize); } for (int i = 0;i < m_ndataSize;i++) { *(static_cast<char*>(m_data) + i) = *obj++; } m_ntype = type_string; return static_cast<char*>(m_data); } inline void* Testauto::GetData(int type) { unsigned long long nMax; long long nMin; long long nLen; long long nData; int len; if (0 != m_data && 0 != m_ndataSize) { len = strlen(static_cast<char*>(m_data)); switch (type) { case type_int16: { nMax = 32767; nMin = -32768; nLen = 5; len = len > sizeof(short) ? len : sizeof(short); break; } case type_uint16: { nMax = 65535; nMin = 0; nLen = 5; len = len > sizeof(unsigned short) ? len : sizeof(unsigned short); break; } case type_int32: { nMax = 2147483647; nMin = -2147483647 - 1; nLen = 10; len = len > sizeof(int) ? len : sizeof(int); break; } case type_uint32: { nMax = 4294967296; nMin = 0; nLen = 10; len = len > sizeof(unsigned int) ? len : sizeof(unsigned int); break; } case type_int64: { nMax = 9223372036854775807; nMin = -9223372036854775808; nLen = 19; len = len > sizeof(long long) ? len : sizeof(long long); break; } case type_uint64: { nMax = 18446744073709551615; nMin = 0; nLen = 20; len = len > sizeof(unsigned long long) ? len : sizeof(unsigned long long); break; } default: { nMax = 9223372036854775807; nMin = -9223372036854775808; nLen = 19; len = len > sizeof(long long) ? len : sizeof(long long); break; } } switch (m_ntype) { case type_string: { if (0 == m_Condata) { m_Condata = ::operator new(len); m_nCondataSize = len; } else if (m_nCondataSize != len) { delete[] m_Condata; m_Condata = ::operator new(len); m_nCondataSize = len; } memset(m_Condata,0,len); memcpy(m_Condata,m_data,len); if (nLen <= len && -1 < _atoi64(static_cast<char*>(m_Condata))) { memcpy(m_Condata,m_data,nLen); if (nMax < _atoi64(static_cast<char*>(m_Condata))) { memset(m_Condata,0,len); memcpy(m_Condata,m_data,nLen - 1); nData = _atoi64(static_cast<char*>(m_Condata)); } else { nData = _atoi64(static_cast<char*>(m_Condata)); } } else if (nLen <= len && nMin > _atoi64(static_cast<char*>(m_Condata)) && 0 != nMin) { memset(m_Condata,0,len); memcpy(m_Condata,m_data,nLen + 1); nData = _atoi64(static_cast<char*>(m_Condata)); } else if (nMin > _atoi64(static_cast<char*>(m_Condata)) && 0 == nMin) { nData = 0; } else { memcpy(m_Condata,m_data,len); nData = _atoi64(static_cast<char*>(m_Condata)); } } break; default: long long nRem; switch (m_ntype) { case type_int8: nRem = *static_cast<char*>(m_data); break; case type_uint8: nRem = *static_cast<unsigned char*>(m_data); break; case type_int16: nRem = *static_cast<short*>(m_data); break; case type_uint16: nRem = *static_cast<unsigned short*>(m_data); break; case type_int32: nRem = *static_cast<int*>(m_data); break; case type_uint32: nRem = *static_cast<unsigned int*>(m_data); break; case type_int64: nRem = *static_cast<long long*>(m_data); break; case type_uint64: nRem = *static_cast<unsigned long long*>(m_data); break; default: nRem = *static_cast<long long*>(m_data); break; } if (0 == nMin && nMin > nRem) { nData = 0; } else if (nMin > nRem) { while (nMin > nRem) { nRem /= 10; } nData = nRem; } else if (nRem > nMax && 0 < nRem) { while (nRem > nMax&& 0 < nRem) { nRem /= 10; } nData = nRem; } else { nData = nRem; } break; } return static_cast<void*>(&nData); } return NULL; } inline char* Testauto::Outstring() { if (0 != m_data && 0 != m_ndataSize) { if (0 == m_Condata) { m_Condata = ::operator new(m_ndataSize * 3); m_nCondataSize = m_ndataSize * 3; } else if (m_nCondataSize != m_ndataSize * 3) { delete[] m_Condata; m_Condata = ::operator new(m_ndataSize * 3); m_nCondataSize = m_ndataSize * 3; } memset(m_Condata,0,m_nCondataSize); switch (m_ntype) { case type_int8: ltoa(*static_cast<char*>(m_data),static_cast<char*>(m_Condata),10); break; case type_uint8: ltoa(*static_cast<unsigned char*>(m_data),static_cast<char*>(m_Condata),10); break; case type_int16: ltoa(*static_cast<short*>(m_data),static_cast<char*>(m_Condata),10); break; case type_uint16: ltoa(*static_cast<unsigned short*>(m_data),static_cast<char*>(m_Condata),10); break; case type_int32: ltoa(*static_cast<int*>(m_data),static_cast<char*>(m_Condata),10); break; case type_uint32: ltoa(*static_cast<unsigned int*>(m_data),static_cast<char*>(m_Condata),10); break; case type_int64: _i64toa(*static_cast<long long*>(m_data),static_cast<char*>(m_Condata),10); break; case type_uint64: _i64toa(*static_cast<unsigned long long*>(m_data),static_cast<char*>(m_Condata),10); break; case type_string: memcpy(m_Condata,m_data,m_ndataSize); break; default: memcpy(m_Condata,m_data,m_ndataSize); break; } return static_cast<char*>(m_Condata); } return NULL; } inline int Testauto::Format(const char *fmt, ...) { va_list args; int i; char buf[10240 * 100] = ;/* Maximum input 1M bytes */ va_start(args, fmt); i = vsprintf(buf, fmt, args); va_end(args); int len = strlen(buf); if (0 >= len) { return -1; } if (0 == m_data && 0 == m_ndataSize) { m_ndataSize = len; m_data = ::operator new(m_ndataSize); } else if (m_ndataSize != len) { m_ndataSize = len; delete[] m_data; m_data = ::operator new(m_ndataSize); } memcpy(m_data,buf,len); m_ntype = type_string; return i; } class Test1//This is a custom reference class { public: Test1():nNum(0),nData(0) { } int nNum; int nData; };
Paste a reference below:
Testauto testte;//Class structure object Test1 testtest12;//Custom Reference Class Object testtest12.nNum = 1; testtest12.nData = 2; WriteType(testte,&testtest12,Test1);//Incoming Test1 class object Test1 testtest123 = *static_cast<Test1*>(testte.GetObj());//Class objects can be output statically Test1 testtest123 = *(Test1*)testte.GetObj();//Class objects can also be cast out ((Test1*)testte.GetObj())->nNum = 5;//Stored class object variables can be modified directly testte = /*(char*)*/"-1234567890";//Incoming String short testchar1234 = testte.OutShort();//Output in short ranges from 32767 to -32768, where -12345 int testchar123412 = testte.OutInt();//Output number range in int is 217483647 ~ -2147483648, here is -1234567890 char* testchar12345 = testte.Outstring();//Output "-1234567890" as a string here testte.Format("%s%d!","123",456);//Format input string in CString-like form testchar12345 = testte.Outstring();//Output "123456!" *testchar12345 = '9';//Modified to "923456!" testchar12345 = testte.Outstring();//Output "123456!" again
Here's a demonstration of some of these methods. Types in enum definitions can be converted arbitrarily. If any friend is interested in floating point numbers, they can add their own tests or make suggestions ~~Thank you!
Source code address: http://download.csdn.net/detail/a29562268/9844092!
View column details Unlock all columns now Dayu Blog Specialist 94 original articles were published. 206 were approved. 180,000 visits+ Private letter follow