我在使用模板时遇到了一个新问题。这是我最近阅读的一本书中的一点创意,扩展了他的想法,并且它有这个代码示例。
假设你有一个模板化的Array2D类。你有这个方法(Array2D :: WriteFile):
bool WriteFile( const char* p_filename )
{
FILE* outfile = 0;
int written = 0;
// open the file
outfile = fopen( p_filename, "wb" );
// return if it couldn't be opened
if( outfile == 0 )
return false;
// write the array and close thef ile
written = fwrite( m_array, sizeof( Datatype ), m_size, outfile );
fclose( outfile );
// if we didn't write the number of items we expected,
// return failure
if( written != m_size )
return false;
// return success.
return true;
}
这适用于基本数据类型,如int,char,float等。但是,如果你有一点创意,使数据类型成为复合变量,如SLinkedList(单链表)。它将是Array2D。然后你调用旧的WriteFile()函数。它会保存它,但你只保存了一个节点。剩下的节点都被遗忘了,永远不会回来。
我脑子里浮现出一些想法: 在你的截止日期前,看着时钟旋转你的拇指。 2.使Array2D :: WriteFile()成为一个纯虚函数,使更具体的类以它应该的方式保存它。但是我不能在其他独立的情况下单独使用Array2D。 3.编写一个函数指针来保存,但我认为它可能会变得混乱,因为你不知道你传入的数据是什么时候到来。它可能会根据数据类型而有所不同。 4.也许,实现模板不是解决方案。
模板类没有根据数据类型为我解决每种情况。那么您认为什么是好的解决方案?谢谢!
答案 0 :(得分:4)
您的对象需要可序列化。当你试图以这种方式写出链表的头部时,想想实际发生的事情 - 当然它只是写第一个节点; write
函数不知道它正在写什么,所以它不知道如何遵循指向下一个节点的指针并写出来。它只是看到位并将它们写出来直到当前对象的结尾,在这种情况下只是第一个节点。
序列化基本上意味着,对于每个非平凡类型,编写一个方法,将该类型打包成适合写出的平面字节流(理想情况下也是读取该格式的第二种方法)。
现在,您的问题被标记为C ++,但您编写的代码非常类似于C语言。在C ++中实现可序列化对象的常规方法是使用<<
参数覆盖std::ostream&
运算符并返回值,例如
std::ostream& MyType::operator<< (std::ostream& out)
{
// Here, write out the logical contents of this object in whatever format you
// feel is appropriate (keep in mind endianness and floating point representation
// if you want portability!)
return out << this->field1 << this->field2 << this->field3;
}
对称
std::istream& MyType::operator>> (std::istream& in)
{
// Here, read in the logical contents of this object in the same format
return in >> this->field1 >> this->field2 >> this->field3;
}
现在,您可以这样做:
MyType t;
std::ofstream outputFile("myoutputfile.dat");
outputFile << t;
请注意,这种覆盖流运算符的方法意味着,例如,如果MyType::field2
本身就是一个复杂的对象,只要它,它仍然可以在上面的代码中正确地序列化和反序列化。 流操作符被覆盖。
但是如果你想继续使用原始帖子中的C风格文件I / O,事情就不会那么干净了。如果您的代码确实应该是C ++,那么您应该使用iostream库来执行文件I / O.
答案 1 :(得分:2)
你可以简单地使用iostreams
等价物。而不是使用作为C函数的fwrite
并且仅适用于C数据类型,而是使用可以重载并专门用于自定义类型的C ++等价物。
std::ofstream file(p_filename);
file << m_array;
operator <<
适用于所有内置类型,对于自定义类型,您可以自行定义。
答案 2 :(得分:1)
我的直接反应是,您正在查看之前已经查看过(并且至少在某种程度上已经解决过)的问题。是的,它仍然可以使用相当多的模板。我会看一下std::copy
和std::ostream_iterator
以及一些序列化库,例如Boost serialization。