在 C++ 中通过赋值初始化自己的 String 类

Posted

技术标签:

【中文标题】在 C++ 中通过赋值初始化自己的 String 类【英文标题】:initialize own String class by assignment in c++ 【发布时间】:2015-09-02 08:53:53 【问题描述】:

我正在用 c++ 编写自己的字符串类 StringEx(别担心,只是为了练习),但我无法通过为其分配字符串来创建我的类的实例:

StringEx string1 = StringEx("test"); // works fine
StringEx string2 = "test"; // doesn't work

string string3 = "test";
string1 = string3; // also works fine

我重载了赋值运算符,以便它可以处理std::string,但我必须先创建一个StringEx 的对象。

如何通过分配字符串来创建StringEx 的新对象?是否有可能让 c++ 处理每个 "string" 作为我的 StringEx 类的对象?

这是我的StringEx.h 现在可以使用

#ifndef STRINGEX_H
#define STRINGEX_H


#include <iostream>
#include <string>
#include <vector>
using namespace std; //simplyfying for now

class StringEx

private:
    vector<char> text;
public:
    StringEx();
    StringEx(string);
    StringEx(const char*);  // had to add this
    StringEx(vector<char>);

    int size() const;
    int length() const;
    char at(int) const;

    void append(const string&);
    void append(const StringEx&);
    void append(const char*);  // had to add this

    StringEx operator+(const string&);
    StringEx operator+(const StringEx&);
    StringEx operator+(const char*);  // had to add this too

    StringEx operator=(const string&);
    StringEx operator=(const StringEx&);
    StringEx operator=(const char*);  // had to add this too

    StringEx operator+=(const string&);
    StringEx operator+=(const StringEx&);
    StringEx operator+=(const char*);  // had to add this too

    friend ostream& operator<<(ostream&, const StringEx&);
;

#endif // STRINGEX_H

【问题讨论】:

这称为初始化(更准确地说,复制初始化),而不是赋值。赋值是在对象之前已经构造的时候(就像在你的上一个例子中一样)。 奇怪的是:这段代码在 VS2015 上编译得很好 你已经得到了一些答案,但你真的应该展示你的类的构造函数、复制构造函数和复制赋值的声明。 @SimonKraemer MSVC 从来都不是标准合规的典范。 @LPrulzcrossover 您的编辑显示了导致错误的StringEx.h,还是现在有效的StringEx.h?请编辑您的问题并解释您所展示的内容。 【参考方案1】:

一些精度:

StringEx string1 = StringEx("test"); // works fine

这使用复制构造函数,即StringEx(const StringEx&amp; other);

StringEx string2 = "test"; // doesn't work

这会尝试使用具有以下签名的构造函数:StringEx(const char* str);

最后,这两行:

string string3 = "test";
string1 = string3; // also works fine

从标准库定义的const char* 创建一个std::string,然后使用您似乎已正确定义的std::string 重载的复制赋值运算符,即StringEx&amp; operator=(const std::string&amp; other)

这里的重点是这样的说法:

Type myVar = something;

不是赋值,它是使用构造函数的变量的声明和初始化,而不是复制赋值运算符。

在您的情况下,您只是缺少一个将const char* 作为参数的构造函数

【讨论】:

原代码可以用MSVC14/VS2015编译,运行正常。即使 IDE 显示错误。 谢谢,现在可以使用了!是否有可能让 c++ 处理每个const char* 作为StringEx?为了得到即cout &lt;&lt; "hello" + "world";工作。 @LPrulzcrossover 你不能隐含地(好吧,也许你可以用一种我不知道的非常丑陋的方式)。你为什么要那样做?该行可以使用适当的 operator+ 重载来处理两个 const char*,例如返回 std::string 是否有可能为两个const char* 重载operator+?考虑到this,答案似乎是否定的,或者你会怎么做? 之前应该检查过,实际上不可能。 §13.5.6 中的 C++ 标准规定,在重载二元运算符时,至少一个参数类型必须是类、对类的引用、枚举或对枚举的引用。我的错。【参考方案2】:

我假设你有一个表单的非显式构造函数

StringEx (const std::string&);

或类似的。

字符串文字不是std::string 类型。 "test" 的类型为 const char[5]std::string 有一个接受const char* 的非显式构造函数,所以你的两个调用看起来像这样(不考虑复制省略):

//implicitly convert "test" to temporary std::string
//construct temporary StringEx with temporary std::string
//copy-construct StringEx with temporary
StringEx string1 = StringEx("test"); 

//no StringEx constructor taking const char*
//two conversions necessary to make "test" into a StringEx
//invalid
StringEx string2 = "test";

一个简单的解决方法是添加一个构造函数,将const char* 设置为StringEx

StringEx (const char*);

或者你也可以使用直接初始化:

//only one conversion needed
StringEx string2 ("test");

【讨论】:

【参考方案3】:

TLDR:如果需要 2 次“强制转换”,编译器不会自动解析。在这种情况下,const char*std::stringStringEx


StringEx string1 = StringEx("test"); // works fine > 这会显式调用构造函数,因此只需进行一次转换:const char*std::string

StringEx string2 = "test"; // doesn't work > 另一方面,这并不清楚。你想将const char* 转换为std::string 并使用StringEx(const std::string&amp;)constructor 还是使用其他中间类?

你需要的是另一个接受const char*作为参数的构造函数。

顺便说一句:

StringEx string4 = std::string("test"); //Also works

【讨论】:

以上是关于在 C++ 中通过赋值初始化自己的 String 类的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中通过指针传递字符串?

在 C++ 中通过构造函数复制类

C++复合类型

C++ string 初始赋值用char[]会乱码

C++ STL主要组件之String总结(第二部分 深浅拷贝问题以及赋值运算符重载)

从复制赋值重载中通过引用返回