在提問之前我已經看到了一些類似的問題,但我仍然堅持使用operator =.
目前,我可以通過構造方法正確獲取單獨的字串。但是當我編譯代碼時,str[length i] = s[i];方法中的行String& String::operator = (const String& s)顯示錯誤:
'operator[]' 不匹配(運算元型別為 'const String' 和 'unsigned int')
所以我需要你的幫助來修復這個錯誤。
這是我的代碼:
#include <iostream>
#include <cstring>
class String {
// Initialise char array
char* data;
unsigned length;
public:
// Constructor without arguments
String();
// Constructor with 1 arguments
String(char* s);
// Copy Constructor
String(const String& source);
// Move Constructor
String(String&& source);
// Destructor
~String() { delete[] data; }
/*!
* @brief String length.
* @return Value in String @c length.
*/
unsigned len ( ) const;
/*!
* @brief Append to String.
* @param[in] s A String object.
* @return A String reference to *this.
* @post String will equal the concatenation of itself with @a s.
*/
String& operator = (const String& s);
};
// Constructor with no arguments
String::String()
: data{ nullptr }
{
data = new char[1];
data[0] = '\0';
}
// Constructor with one arguments
String::String(char* s)
{
if (s == nullptr) {
data = new char[1];
data[0] = '\0';
}
else {
data = new char[strlen(s) 1];
// Copy character of s[]
// using strcpy
strcpy(data, s);
data[strlen(s)] = '\0';
std::cout << data << "\n";
}
}
// Copy Constructor
String::String(const String& source)
{
data = new char[strlen(source.data) 1];
strcpy(data, source.data);
data[strlen(source.data)] = '\0';
}
// Move Constructor
String::String(String&& source)
{
data = source.data;
source.data = nullptr;
}
unsigned String::len ( ) const
{
return length;
}
String& String::operator = (const String& s)
{
unsigned len = length s.len();
char* str = new char[len];
for (unsigned j=0; j < length; j )
str[j] = data[j];
for (unsigned i=0; i < s.len(); i )
str[length i] = s[i];
delete data;
length = len;
data = str;
return *this;
}
int main()
{
// Constructor with no arguments
String a;
// Convert string literal to
// char array
char temp[] = "Hello world.";
// Constructor with one argument
std::cout << "s1: ";
String s1{ temp };
// Copy constructor
String s11{ a };
char temp1[] = "Goodbye!";
std::cout << "s2: ";
String s2{ temp1 };
String s3 = String s1 String s2;
return 0;
}
main函式的另一種寫法:
int main()
{
String s1("Hello World.");
String s2("Goodbye!");
std::cout << "s1: " << s1 << std::endl;
std::cout << "s2: " << s2 << std::endl;
String s3 = s1 s2;
std::cout << "s3: " << s3 << std::endl;
std::cout << "The last char of s3: " << s3[s3.size()-1] << std::endl;
return 0;
}
預期結果:
s1: Hello World.
s2: Goodbye!
s3: Hello World.Goodbye!
The last char of s3: !
如何修改我的代碼以正確獲取s3和最后一個字符s3?
uj5u.com熱心網友回復:
在您的許多建構式中,您沒有設定lengthwhich 會留下不確定的值 - 讀取這些值會使程式具有未定義的行為。所以,首先解決這個問題:
#include <algorithm> // std::copy_n
// Constructor with no arguments
String::String() : data{new char[1]{'\0'}}, length{0} {}
// Constructor with one argument
String::String(const char* s) { // note: const char*
if (s == nullptr) {
data = new char[1]{'\0'};
length = 0;
} else {
length = std::strlen(s);
data = new char[length 1];
std::copy_n(s, length 1, data);
}
}
// Copy Constructor
String::String(const String& source) : data{new char[source.length 1]},
length{source.length}
{
std::copy_n(source.data, length 1, data);
}
// Move Constructor
String::String(String&& source) : String() {
std::swap(data, source.data);
std::swap(length, source.length);
}
在operator =您嘗試使用下標運算子時String::operator[],但您尚未添加這樣的運算子,因此請s[i]使用s.data[i]:
String& String::operator =(const String& s) {
unsigned len = length s.length;
char* str = new char[len 1];
for (unsigned j = 0; j < length; j ) str[j] = data[j];
for (unsigned i = 0; i < s.length; i ) str[length i] = s.data[i];
str[len] = '\0';
delete[] data; // note: delete[] - not delete
length = len;
data = str;
return *this;
}
如果您希望能夠在String物件上使用下標運算子,則需要添加一對成員函式:
class String {
public:
char& operator[](size_t idx);
char operator[](size_t idx) const;
};
char& String::operator[](size_t idx) { return data[idx]; }
char String::operator[](size_t idx) const { return data[idx]; }
為了String s3 = s1 s2;作業,你需要一個免費的operator 多載:
String operator (const String& lhs, const String& rhs) {
String rv(lhs);
rv = rhs;
return rv;
}
此外,為了支持列印String您在替代main功能中嘗試的內容,您需要operator<<多載。例子:
class String {
friend std::ostream& operator<<(std::ostream& os, const String& s) {
os.write(s.data, s.length);
return os;
}
};
完整演示
uj5u.com熱心網友回復:
對于初學者來說,建構式都沒有設定資料成員length。所以運營商
String& String::operator = (const String& s)
{
unsigned len = length s.len();
char* str = new char[len];
//...
具有未定義的行為。
還假設資料成員長度已初始化您需要撰寫
char* str = new char[len 1];
代替
char* str = new char[len];
為終止零字符 '\0' 保留記憶體,因為您strcpy在復制建構式中使用標準 C 字串函式
strcpy(data, source.data);
并且該類沒有用于 loo[ 的下標運算子
for (unsigned i=0; i < s.len(); i )
str[length i] = s[i];
而且您忘記附加終止零字符'\0'。
注意size這個運算式使用的類中沒有成員函式
s3[s3.size()-1]
而這個建筑
String s3 = String s1 String s2;
是無效的。至少你應該寫
字串 s3 = s1 s2;
并相應地定義運算子 。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/487141.html
上一篇:更改繼承類的成員變數
