2013-05-27 29 views
0

我刚刚意识到我的代码库有点不一致,有些对象是使用构造函数A(const std::string&)从字符串构造而来的,还有一些是使用boost::lexical_cast<A>(const std::string&)从字符串构造的。构造函数从字符串VS词法转换为字符串?

在我的理解中,这些符合相同的需求,但在许多方面表现不尽相同,格式错误的字符串的例外情况和转换是我首先想到的,但我相信也有其他含义。所以我的问题是:我应该使用什么,为什么?


编辑:按@ hetepeperfan的评论,我在改造常量的std :: string &,这是我首先意味着

+0

我认为你的构造函数一般也应该使用const std :: string,除非你的构造函数真的需要改变字符串。 – hetepeperfan

+0

'boost :: lexical_cast (U)'如果'U'有输出运算符并且'T'有输入运算符''可以将'U'转换为'T' ...但是你的c'tor取决于它是如何实现的。 – ForEveR

+0

@hetepeperfan对,我只是改变了它。 –

回答

2

我可以想像的的std :: string参数类InputFile(类似于std::ifstream),其采用代表的路径在文件系统中的文件中的字符串:

InputFile f("/dir/file.txt"); 
use(f); 

使用boost::lexical_cast这里至少会有怪异。

我想这种观察可以这样推广:如果您的类型A代表与std::string“可兼容”的值或可转换为std::string,则您有两种选择。但是,如果您在接口中公开一个构造函数,该构造函数将std::string类型的一个非可选参数用于其他目的而不是转换值,则只有使用构造函数才有意义(并且此构造函数应该可能为explicit)。

+0

好点,我或多或少地想着一个消息的序列化字段,你可以随时去两个方向。 –

1

在我的理解,这些实现同样需要[...]

他们不履行同样需要。用于创建对象的接口应该总是最好地表达创建对象后面的语义。词法转换是将字符串值转换(重新解释)为对象实例。如果你的对象是用一个字符串值构造而不是字符串中的值,使用boost :: lexical_cast只会令人困惑。

[...]但是在许多方面表现不尽相同,格式错误的字符串的例外情况和转换是我心目中的第一个例外,但我相信也有其他含义。所以我的问题是:我应该使用什么,为什么?

如果你的对象可以从任何字符串值构造(即不依赖于字符串中的值,但只是复制内部字符串),那么你应该直接把它传递给构造函数。

如果字符串值传递给构造意味着你可以使用无效值创建一个实例,您应该使用工厂函数(即抛出一个错误之前实例化对象)或[更少首选]添加异常验证在构造函数中(不理想,不太干净,在大多数情况下更糟糕的设计)。

如果你的对象实例模型,可以从值的字符串中的解释(一“投”)来创建一个值/类型的专业化,那么你应该支持通过boost::lexical_cast<YourClass>(const std::string&)创建它。

编辑:如果你构建一个对象与名称(例如一些记录器对象),但记录仪的功能/价值并不取决于名字是什么(对象记录相同,只是用不同的名字),那么你不应该定义一个基于lexical_cast的实现(因为这个名字不会改变记录器的功能)。

如果您创建的值/功能对象取决于字符串中的值(解析字符串中的值并将其转换为“复数”类实例),那么实例的行为取决于字符串中的内容(lexical_cast<ComplexNo>("(0 + 0i)")将返回不能被分割的内容,而不是lexical_cast<ComplexNo>("(1 + 0i)"))。在这种情况下(值对象取决于字符串中的内容)应该支持lexical_cast

基本上,为值对象提供基于lexical_cast的实现。

+0

对不起,我不理解你的句子:“如果你的对象是用字符串值而不是字符串中的值构造的,那么使用boost :: lexical_cast就会令人困惑。”你能提供一个例子吗? –

+0

是:请参阅编辑我的文章。 – utnapistim

+0

好吧我现在明白了。看起来像Andrzej的答案一样。 –

相关问题