在 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& 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& operator=(const std::string& other)
。
这里的重点是这样的说法:
Type myVar = something;
不是赋值,它是使用构造函数的变量的声明和初始化,而不是复制赋值运算符。
在您的情况下,您只是缺少一个将const char*
作为参数的构造函数。
【讨论】:
原代码可以用MSVC14/VS2015编译,运行正常。即使 IDE 显示错误。 谢谢,现在可以使用了!是否有可能让 c++ 处理每个const char*
作为StringEx
?为了得到即cout << "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::string
到 StringEx
StringEx string1 = StringEx("test"); // works fine
> 这会显式调用构造函数,因此只需进行一次转换:const char*
到 std::string
。
StringEx string2 = "test"; // doesn't work
> 另一方面,这并不清楚。你想将const char*
转换为std::string
并使用StringEx(const std::string&)
constructor 还是使用其他中间类?
你需要的是另一个接受const char*
作为参数的构造函数。
顺便说一句:
StringEx string4 = std::string("test"); //Also works
【讨论】:
以上是关于在 C++ 中通过赋值初始化自己的 String 类的主要内容,如果未能解决你的问题,请参考以下文章