代码之家  ›  专栏  ›  技术社区  ›  Matt Ball

在C++中,一个类如何在构造函数中取一个常数STD::String和参数,还可以处理null?

  •  4
  • Matt Ball  · 技术社区  · 15 年前

    我正在尝试使用std::string参数创建类,但它也处理空值而不引发异常。下面是代码示例:

    class myString {
    public:
        myString(const std::string& str) : _str(str) {}
        std::string _str;
    };
    
    int main() {
        myString mystr(NULL);
        printf("mystr = <%s>\n", mystr._str.c_str());
        return 0;
    }
    

    直观地说,您会认为该程序应该打印“mystr=<>”并成功退出,但使用g++会出现以下错误:

    terminate called after throwing an instance of 'std::logic_error'  
    what():  basic_string::_S_construct NULL not valid
    

    如何更改这个类,使它将空值转换为“”,而不是引发逻辑错误异常?

    (postscript:正如您所怀疑的那样,“real”实现比这个示例要复杂一些,在构造函数中有几个参数,用str做一些更有趣的事情,并且适当地保持它的私有性。这个例子背后的动机是我们团队中的程序员将倾向于在这个上下文中出于历史目的使用空值,而编译器不会捕捉到这一点。再培训每个人始终使用“”是相对困难的。或者,一个聪明的解决方案也很容易)

    5 回复  |  直到 15 年前
        1
  •  11
  •   P Shved    15 年前

    这里实际发生的是 NULL 被解释为 char const* 正在尝试转换为 std::string (您可以转换C字符串类型 char* 变成stl字符串,对吗?).

    要处理它,可以添加另一个构造函数

    class myString {
    public:
        myString(const std::string& str) : _str(str) {}
        myString(const char* str) : _str(str==NULL?"":std::string(str)) 
        { /* and do something special in the body */ }
        std::string _str;
    };
    

    但如果你在那里不需要什么特别的东西,最好的办法是

    class myString {
    public:
        myString(const std::string& str = "") : _str(str) {}
        std::string _str;
    };
    int main() {
        myString mystr;  //no () here!
        printf("mystr = <%s>\n", mystr._str.c_str());
        return 0;
    }
    
        2
  •  6
  •   Fred Larson    15 年前

    真的,你不能。空不是字符串。但这里有一些选择:

    • 您可以重载构造函数 省略字符串参数。

    • 您可以使用指针而不是 参考文献。

    • 可以将字符串参数设为默认值 “”。

        3
  •  5
  •   dirkgently    15 年前

    你不能。你需要一些能够传递引用的东西。您可以通过默认为空字符串aka来解决这个问题。 "" .

    或者,换一个 explicit CTO:

    class myString {
     public:
       myString(const std::string& str) : _str(str) {}
       explicit myString(const char* str = NULL) : _str(str?str:"") {}
       std::string _str;
    };
    
        4
  •  2
  •   David Seiler    15 年前

    需要提供接受指针作为参数的构造函数。空是一个指针,而不是一个引用,因此,正如您所看到的,如果您试图将其作为字符串引用来处理,将导致灾难。

    尝试:

    class myString {
    public:
        myString(const std::string& str) : _str(str) {}
        myString(const std::string* str) : { /* special-case logic here */}
        std::string _str;
    };
    
        5
  •  0
  •   Mark Ransom    15 年前

    我假设这个问题不像你的例子看起来那么简单。

    您可以创建一个静态变量并分配给它,而不是使用一个空参数。

    class myString {
    public:
        static std::string nullstring;
    ...
    };
    

    在.cpp中的某个地方:

    std::string myString::nullstring("");
    

    并称之为:

    int main() {
        myString mystr(myString::nullstring);
        printf("mystr = <%s>\n", mystr._str.c_str());
        return 0;
    }