我的情况如下:有一些类MyList可能会在稍后获得特定的实现。现在,像std :: vector这样的行为很好。
但是,我真的需要一种简单的方法来调用某种asString()/ toString()方法,因为我需要它在测试断言,调试输出等等。我看到的唯一选择是:
公共继承权。我永远不会通过基指针删除这样的列表,因为永远不应该有任何基本指针。如果我这样做,反正将没有指针成员。但是,经验法则仍然指出:不要从stl容器继承。
某种“全局”(实际上在命名空间中)当然是将MyList的实例作为参数并为我执行asString()魔术的方法。在这种情况下,MyList可能是std :: vector的简单typedef。
我不太喜欢这些选项。还有什么我没想到的吗?或者如果不是 - 我应该选择哪种方式?
答案 0 :(得分:8)
第二种方法有什么问题?这是迄今为止最简单,也很优雅.- 想象一下包装矢量的替代方案。这将导致你很多额外的工作和胶水代码容易出错!我肯定会采用功能方法!
编辑:顺便说一句,我几乎只使用免费功能(有时是静态成员)进行转换。想象一下,你有一些类型的东西,不知何故需要转换为字符串。让toString()函数作为自由函数而不是成员不会让你头疼,因为你基本上可以简单地重载函数,而不必触及任何现有的类(或者可能)您甚至没有源访问权限的类。)
然后你可以有一个像:
这样的功能template<class T>
void printDebugInfo(const T & _obj)
{
std::cout<<toString(_obj)<<std::endl;
}
你不会遇到你遇到的限制。
答案 1 :(得分:6)
实际上,类类型的自由函数是一种标准技术,被认为是类型接口的一部分。阅读Herb Sutter的this GotW,这是一位在C ++标准化方面有发言权的人。
通常,更喜欢免费功能而不是成员功能。这增加了封装和可重用性,并减少了类膨胀和coupling。请参阅Scott Meyers的this article以获取更深入的信息(如果您希望提高对C ++的有效和清晰使用,那么您应该阅读的C ++书籍备受推崇。)
另请注意,您永远不应从STL容器派生。它们不是作为基类设计的,您可以轻松调用未定义的行为。但请参阅Is there any real risk to deriving from the C++ STL containers?。
答案 2 :(得分:3)
我认为有一个免费的
std::string toString( const MyList &l );
功能非常好。如果您害怕名称冲突,可以按照您的说法考虑命名空间。此函数高度分离,无法修改MyList
个对象的私有成员(如成员或朋友函数的情况)。
只有 的理由才能证明它不是免费功能:你注意到你突然需要扩展MyList的公共接口,以便能够正确实现toString
。在那种情况下,我会把它变成朋友的功能。
答案 3 :(得分:2)
如果你做了类似的事情:
template<typename T>
std::ostream& operator<< (std::ostream &strm, const MyList<T> &list)
{
if (list.empty())
return strm;
MyList<T>::const_iterator iter = list.begin(),
end = list.end();
// Write the first value
strm << *iter++;
while (iter != end)
strm << "," << *iter++;
return strm;
}
那么只要元素实现了流媒体操作符,你就可以为列表中的任何内容添加一个字符串
答案 4 :(得分:1)
您是否考虑过组成,而不是继承?即,您的MyList
的成员变量类型为std::vector
。
您可能会抱怨现在需要在std::vector
中复制MyList
的API。但是你说你可能会在以后更改实现,所以无论如何你都需要这样做。您也可以立即执行此操作,以避免以后更改所有客户端代码。
答案 5 :(得分:1)
在这种情况下,继承是完全错误的。
全球功能方法非常好。
C ++中的一种“方法”是重载operator <<
并使用stringstream
来输出你的矢量或其他东西。
答案 6 :(得分:1)
我会使用全局模板函数printOnStream。这样,您可以轻松添加对其他数据类型的支持,并且使用流比创建字符串更通用。
我不会使用继承,因为可能会有一些棘手的情况。基本的是你提到的 - 缺少虚拟析构函数。但是,所有期望std :: vector的东西都无法正常处理您的数据类型 - 例如,您可能遇到切片问题。
答案 7 :(得分:0)
为什么调试和断言方法不能为您执行此操作?