2011-08-29 26 views
1

我的情况如下:有一些MyList类可能会在稍后得到特定的实现。目前,像std :: vector这样的行为很好。但是,我真的需要一种简单的方法来调用某种asString()/ toString()方法,因为我需要它在测试断言,调试输出等等。我看到的唯一选项是:如何将asString()/ toString()添加到std :: vector?

  1. 公有遗传。我永远不会通过基指针删除这样的列表,因为不应该有任何基指针。如果我这样做,无论如何都不会有指针成员。然而,经验法则仍然指出:不要从stl容器继承。

  2. 某种“全局”(实际上在命名空间中,当然)方法,它将MyList的实例作为参数并为我执行asString()魔术。在这种情况下,MyList可以是std :: vector的简单typedef。

我不喜欢这些选项太多。还有什么我没有想到的?或者如果不是,我应该选择哪种方式?

回答

8

第二种方法有什么问题?这是迄今为止最简单也很优雅.-想象一下包裹矢量的替代方案。这会导致你很多额外的工作和胶水代码,容易出错!我肯定会使用函数方法!

编辑:顺便说一句,我几乎完全使用免费功能(有时静态成员)进行转换。想象一下你有一些需要转换为字符串的类型。将toString()函数作为自由函数而不是成员不会让你头疼,因为基本上你可以根据需要简单地重载函数,而不必触摸任何现有类(或者可能你甚至没有源访问权限的类)。

然后你就可以有这样一个功能:

template<class T> 
void printDebugInfo(const T & _obj) 
{ 
    std::cout<<toString(_obj)<<std::endl; 
} 

,你不会有您所遇到的制约因素。

0

为什么你的调试和断言方法不能为你做到这一点?

+1

分离,我想。调试框架为什么要负责知道如何显示“MyList”? –

1

您是否考虑过构图而不是继承?即您的MyList有一个std::vector类型的成员变量。

您可能会抱怨您现在需要复制std::vector的API MyList。但是你说你可能会稍后改变实现方式,所以无论如何你都需要这样做。你可以马上做,以避免以后改变所有的客户代码。

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?

1

在这种情况下继承是完全错误的。

全局函数法非常好。

C++中的一种'方式'是重载operator <<并使用stringstream来输出你的向量或其他东西。

3

我认为有一个免费

std::string toString(const MyList &l); 

功能完全正常。如果您害怕名称冲突,那么您可以考虑使用名称空间。此功能是高度分离的,并且将无法修补MyList对象的私人成员(如成员或朋友功能的情况)。

只有原因,因此有理由不使它成为一个自由的功能:你注意到你突然需要延长MYLIST的公共接口很多,只是为了能够实现toString正常。在这种情况下,我会让它成为朋友功能。

1

我会去全球模板功能printOnStream。这样,您可以轻松地添加对其他数据类型的支持,并且使用流比创建字符串更普遍。

我不会使用继承,因为可能会有一些棘手的情况。基本的东西就像你所说的 - 缺乏虚拟析构函数。但是,也期望std :: vector的所有东西都不能正确处理你的数据类型 - 例如你可能会遇到切片问题。

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; 
} 

然后你就基本上是有一个字符串列表中的任何东西,只要元素实现流媒体运营商的关注

+0

你是哪个运算符超载?但我嗅到了一个很好的答案。 /修正了你的代码,现在得到我的upvote。 –

+0

啊,我忘了'''吗?但是,是的,这就是我所要做的 – Mranz