这些过载是否必要?

时间:2011-07-29 08:40:23

标签: c++ overloading

我必须编写一个包含一个带两个字符串参数的函数的库:

void foo(const std::string& arg1, const std::string& arg2);

我的图书馆将被一些不喜欢C ++并且仅用于const char*的人使用。

为了满足他们的喜好,我改变了原型:

void foo(const char* arg1, const char* arg2);

让我的第一个版本成为一个简单的内联调用:

inline void foo(const std::string& arg1, const std::string& arg2)
{
  foo(arg1.c_str(), arg2.c_str());
}

当然,多亏了std::string构造函数,它与第一个版本的工作方式几乎相同。编写此重载只会避免在有人仅通过std::string的情况下实现无用的const char*

但现在我想知道:这种过载真的有必要还是只是过早优化?

另外,我觉得这在某种程度上是不完整的:我还应该写void foo(const char* arg1, const std::string& arg2)void foo(const std::string& arg1, const char* arg2)重载吗?如果我有3个,4个或更多个(n)参数怎么办?我应该写2 n 重载吗?

简而言之,您是否遇到过类似情况?你做了什么选择以及为什么?

谢谢。

6 个答案:

答案 0 :(得分:4)

IMO合理地有两个重载来处理组织中共存的两种不同的编程风格。

从技术上讲,它不是只是优化:

  1. const char*可以是extern "C",因此可能对其他语言的绑定很有用,甚至可能对来自dll边界的其他C ++代码与不兼容的标准库实现有用。
  2. 转换为std::string可以抛出bad_alloc,所以如果它不能失败,那么如果你有一个C风格的字符串并希望在一个C风格的字符串中使用它,则const char*版本很有用。 nothrow context。
  3. 还要注意原则c_str()可以抛出bad_alloc,但我怀疑任何实现都会实现。

    2 n 重载对我来说似乎不值得 - 如果有人混合stringchar*那么它不仅仅是编程风格的区别,它们实际上正在使用混合格式由于某种原因。由于他们已经使用了两者,他们可以自己转换。

    这一切都假定该功能足够简单,您很乐意使用const char*参数实现实际工作。如果基于string的实现会明显更简单(例如,如果它需要大量代码使其异常安全),那么无论如何这可能胜过效率,所以不要提供任何重载,让他们的{ {1}}转换为const char*

答案 1 :(得分:2)

只要你想使用C ++(而不是C语言),第二个似乎是不必要的,如果你有这个:

void foo(const std::string& arg1, const std::string& arg2);

您可以将std::stringchar*的所有组合称为:

char *ca, *cb;
std::string sa, sb;
//...
foo(ca,cb); //char*, char*
foo(sa,cb); //std:string, char*
foo(sa,sb); //std::string, std::string
foo(ca,sb); //char*, std::string

答案 2 :(得分:1)

如果const char * text永远不为null,则可以使用string,因为它具有implictit构造函数,因此string类版本就足够了。另一方面:如果const char * text可以为null,则会生成运行时错误。

还有一件事:在DLL接口上,STL并不是一个很好的选择。因此,如果函数是DLL接口的一部分,则可以使用C样式字符串。

我可以这样做:

#include <string>
using namespace std;

void foo( const string arg0, const string arg1 )
extern "C" _declspec( dllexport ) void foo( const char * arg0, const char * arg1 )
{
  string string_arg0, string_arg1;
  if ( arg0 != 0 )
    string_arg0 = arg0;
  if ( arg1 != 0 )
    string_arg1 = arg1;
  foo(string_arg0, string_arg1);
}

答案 3 :(得分:0)

我认为你现在的做法是正确的。你为const char*重载的地方,并提供一个也提供std::string的包装器。

如果你的同事打算使用C风格的字符指针而不是那样做(现在的方式)。见以下案例;

char *p = 0;
foo(p);

void foo (const string &s)
{  // runtime error
}

Demo。正如您所看到的那样,角色指针可能不会始终与std::string一致;那么为什么要抓住机会呢。尽管人们可能不会做这样的编码;仍然应该避免这种潜在的危险,以便长期维护。

在函数内部,您始终可以选择std::string中的const char*并编写算法。

答案 4 :(得分:0)

在这种情况下,您可能只需要(const char *,const char *)并让每个人使用std :: string来使用c_str()。这样就不会有任何内存分配开销,只有人们必须编写代码的额外c_str()。

答案 5 :(得分:0)

  

我的图书馆将被一些不喜欢C ++的人使用   仅用于const char *。

告诉他们操作并学习编译器编译的语言。你接受std::string,因为这是在C ++中如何做到的,如果他们不喜欢它,那么他们可以得到一个C编译器。