用重载运算符做String

本文深入探讨了C++中字符串类的实现细节,包括构造、赋值、运算符重载以及比较等核心功能。
#ifndef _STRING_
#define _STRING_
#include <iostream>
using std::ostream;
using std::istream;
class String
{
private:
char *s;
public:
String();
String(int n);
String(const char *str);
String(const String& s2);
~String();
String& operator = (const char *str);
String& operator = (const String& s1);
friend String& operator + (const String& s1,const String& s2);
friend bool operator == (const String& s1,const String& s2);
friend bool operator != (const String& s1,const String& s2);
friend bool operator >= (const String& s1,const String& s2);
friend bool operator <= (const String& s1,const String& s2);
friend bool operator >  (const String& s1,const String& s2);
friend bool operator <  (const String& s1,const String& s2);
friend ostream& operator << (ostream& output,const String& s1);
friend istream& operator >> (istream& input ,String& s1);

};


#endif

#include<String.h>
#include<cstring>
#include<iostream>
using std::ostream;
using std::istream;
using std::endl;
using std::cout;
String s3;
String::String()
{
s=new char[100];
s[0]='\0';
}
String::String(int n)
{
s=new char[n];
s[0]='\0';
}
String::String(const char *str)
{
s=new char[100];
strcpy(s,str);
}
String::String(const String& s2)
{
strcpy(s,s2.s);
}
String::~String()
{
if(s!=NULL)
delete []s;
}
String& String::operator = (const char *str)
{
strcpy(s,str);
return *this; 
}
String& String::operator = (const String& s1)
{
strcpy(s,s1.s);
return *this;
}
String& operator + (const String& s1,const String& s2)
{
extern String s3;
strcat(s3.s,s1.s);
strcat(s3.s,s2.s);
return s3;
}
bool operator == (const String& s1,const String& s2)
{
if(strcmp(s1.s,s2.s)==0)
{
return true;
}
else
{
return false;
}
}
bool operator != (const String& s1,const String& s2)
{
if(strcmp(s1.s,s2.s)==0)
{
return false;
}
else
{
return true;
}
}
bool operator >= (const String& s1,const String& s2)
{
if(strcmp(s1.s,s2.s)>=0)
{
return true;
}
else
{
return false;
}
}
bool operator <= (const String& s1,const String& s2)
{
if(strcmp(s1.s,s2.s)<=0)
{
return true;
}
else
{
return false;
}
}
bool operator >  (const String& s1,const String& s2)
{
if(strcmp(s1.s,s2.s)>0)
{
return true;
}
else
{
return false;
}
}
bool operator <  (const String& s1,const String& s2)
{
if(strcmp(s1.s,s2.s)<0)
{
return true;
}
else
{
return false;
}
}
ostream& operator << (ostream& output,const String& s1)
{
output<<s1.s;
return output;
}
istream& operator >> (istream& input ,String& s1)
{
input>>s1.s;
return input;
}


#include<iostream>
#include<String.h>
using std::cin;
using std::cout;
using std::endl;
int main(int argc, char const *argv[])
{
String A("Poi");
cout<<A<<endl;
String B("ioP");
cout<<B<<endl;
String C;
String D(A);
cout<<D<<endl;
C=A+B;
cout<<C<<endl;
String E("A");

if(A==D) cout<<"A==D"<<endl;
if(A<=B) cout<<"A<=B"<<endl;
if(A>=E) cout<<"A>=E"<<endl;
if(A<B) cout<<"A<B"<<endl;
if(A>E) cout<<"A>E"<<endl;
if(A!=B) cout<<"A!=B"<<endl;
return 0;

}


<think>### 重载运算符详解 运算符重载Operator Overloading)允许为自定义类型(类或枚举)定义运算符的行为。通过重载运算符,可以使自定义类型支持类似内置类型的操作(如 `+`, `-`, `<<` 等)。 #### 核心规则 1. **可重载运算符**: C++允许重载大部分运算符,但以下运算符**不能重载**: - 作用域解析运算符 `::` - 成员访问运算符 `.` - 成员指针访问运算符 `.*` - 条件运算符 `?:` - `sizeof` - `typeid` - `alignof` - `static_cast` 等类型转换运算符(但可重载用户定义的类型转换) 2. **重载方式**: - **成员函数重载**:运算符作用于类的对象 - **全局函数重载**:通常需要声明为类的友元以访问私有成员 3. **参数限制**: - 至少一个参数为用户自定义类型(避免修改内置类型运算符行为) - 不能改变运算符的优先级和结合性 - 不能改变运算符的目数(如 `+` 是二元运算符) #### 常用运算符重载示例 ##### 1. 二元运算符(以 `+` 为例) **成员函数形式**: ```cpp class Vector { public: double x, y; Vector(double x = 0, double y = 0) : x(x), y(y) {} // 成员函数重载 + Vector operator+(const Vector& other) const { return Vector(x + other.x, y + other.y); } }; ``` **全局函数形式**(通常配合友元): ```cpp class Vector { // 声明全局运算符为友元 friend Vector operator+(const Vector& v1, const Vector& v2); private: double x, y; public: Vector(double x = 0, double y = 0) : x(x), y(y) {} }; Vector operator+(const Vector& v1, const Vector& v2) { return Vector(v1.x + v2.x, v1.y + v2.y); } ``` ##### 2. 一元运算符(以 `-` 负号为例) **成员函数形式**: ```cpp class Vector { public: double x, y; // ... 构造函数 // 一元负号运算符 Vector operator-() const { return Vector(-x, -y); } }; ``` ##### 3. 输入/输出运算符(`<<` 和 `>>`) **全局函数重载**(必须): ```cpp #include <iostream> class Point { friend std::ostream& operator<<(std::ostream& os, const Point& p); friend std::istream& operator>>(std::istream& is, Point& p); private: int x, y; public: Point(int x = 0, int y = 0) : x(x), y(y) {} }; // 输出运算符 std::ostream& operator<<(std::ostream& os, const Point& p) { os << "(" << p.x << ", " << p.y << ")"; return os; } // 输入运算符 std::istream& operator>>(std::istream& is, Point& p) { is >> p.x >> p.y; return is; } ``` ##### 4. 赋值运算符(`=`) **成员函数重载**(必须): ```cpp class String { private: char* data; size_t size; public: // 构造函数、析构函数等... // 赋值运算符 String& operator=(const String& other) { if (this != &other) { // 防止自赋值 delete[] data; // 释放旧资源 size = other.size; data = new char[size + 1]; std::copy(other.data, other.data + size + 1, data); } return *this; // 返回当前对象引用 } }; ``` #### 特殊运算符重载 ##### 下标运算符 `[]` **成员函数形式**: ```cpp class Array { private: int* arr; int size; public: Array(int size) : size(size) { arr = new int[size]; } ~Array() { delete[] arr; } // 可修改元素的版本 int& operator[](int index) { if (index < 0 || index >= size) throw std::out_of_range("索引越界"); return arr[index]; } // 常量版本(用于const对象) const int& operator[](int index) const { if (index < 0 || index >= size) throw std::out_of_range("索引越界"); return arr[index]; } }; ``` ##### 函数调用运算符 `()` **创建函数对象(仿函数)**: ```cpp class Multiplier { public: double operator()(double a, double b) const { return a * b; } }; int main() { Multiplier mul; std::cout << mul(3.5, 2.0); // 输出 7.0 } ``` #### 注意事项 1. **自赋值处理**:赋值运算符中必须检查 `this != &other`。 2. **返回值优化**: - 赋值运算符返回 `T&` 以支持链式赋值(`a = b = c`)。 - 算术运算符返回新对象(值返回)。 3. **对称运算符处理**:如 `+` 建议用全局函数实现,以支持 `(T + U)` 和 `(U + T)` 对称性。 --- &sect;&sect;相关问题&sect;&sect;: 1. 为什么赋值运算符通常返回当前对象的引用(`T&`)? 2. 如何重载递增运算符(`++`)的前缀和后缀形式? 3. 类型转换运算符重载的语法是什么?需要注意什么? 4. 在什么情况下必须将运算符重载为全局函数而非成员函数? </think> ### 运算符重载详解 运算符重载允许为自定义类型(类或结构体)定义运算符的行为,使其支持类似内置类型的操作。运算符重载通过特殊的成员函数或全局函数实现。 #### 基本规则: 1. **可重载运算符**:C++允许重载大部分运算符,但不能重载 `::`、`.`、`.*`、`?:`、`sizeof`、`typeid` 等 2. **操作数要求**:至少一个操作数必须是用户定义类型 3. **不能改变**:运算符的优先级、结合性和操作数个数 #### 重载方式: 1. **成员函数形式**(隐含 `this` 指针作为左操作数) 2. **全局函数形式**(常声明为类的友元) #### 常用运算符重载示例: ##### 1. 算术运算符重载(`+`) ```cpp class Vector { public: double x, y; // 成员函数形式 Vector operator+(const Vector& other) const { return {x + other.x, y + other.y}; } }; // 全局函数形式(可实现交换律) Vector operator+(double scalar, const Vector& v) { return {scalar + v.x, scalar + v.y}; } ``` ##### 2. 关系运算符重载(`==`, `<`) ```cpp class Date { int year, month, day; public: // 成员函数形式 bool operator==(const Date& other) const { return year == other.year && month == other.month && day == other.day; } // 全局函数形式 friend bool operator<(const Date& a, const Date& b); }; bool operator<(const Date& a, const Date& b) { if (a.year != b.year) return a.year < b.year; if (a.month != b.month) return a.month < b.month; return a.day < b.day; } ``` ##### 3. 流运算符重载(`<<`, `>>`) ```cpp class Person { std::string name; int age; public: friend std::ostream& operator<<(std::ostream& os, const Person& p); friend std::istream& operator>>(std::istream& is, Person& p); }; std::ostream& operator<<(std::ostream& os, const Person& p) { return os << "Name: " << p.name << ", Age: " << p.age; } std::istream& operator>>(std::istream& is, Person& p) { std::cout << "Enter name and age: "; return is >> p.name >> p.age; } ``` ##### 4. 下标运算符重载(`[]`) ```cpp class IntArray { int* data; size_t size; public: IntArray(size_t n) : size(n), data(new int[n]) {} ~IntArray() { delete[] data; } // 非常量版本(可修改元素) int& operator[](size_t index) { if (index >= size) throw std::out_of_range("Index out of range"); return data[index]; } // 常量版本(只读访问) const int& operator[](size_t index) const { if (index >= size) throw std::out_of_range("Index out of range"); return data[index]; } }; ``` ##### 5. 函数调用运算符重载(`()`) ```cpp class Multiplier { double factor; public: Multiplier(double f) : factor(f) {} double operator()(double x) const { return x * factor; } }; // 使用示例 Multiplier times2(2.0); double result = times2(3.14); // 返回 6.28 ``` #### 特殊运算符重载: ##### 递增/递减运算符(`++`, `--`) ```cpp class Counter { int count; public: Counter() : count(0) {} // 前缀递增 (++obj) Counter& operator++() { ++count; return *this; } // 后缀递增 (obj++) Counter operator++(int) { Counter temp = *this; ++count; return temp; } }; ``` ##### 赋值运算符(`=`) ```cpp class String { char* data; size_t length; public: // 拷贝赋值运算符 String& operator=(const String& other) { if (this != &other) { delete[] data; length = other.length; data = new char[length + 1]; std::strcpy(data, other.data); } return *this; } // 移动赋值运算符 (C++11) String& operator=(String&& other) noexcept { if (this != &other) { delete[] data; data = other.data; length = other.length; other.data = nullptr; other.length = 0; } return *this; } }; ``` #### 注意事项: 1. **保持一致性**:相关运算符应一起重载(如 `==` 和 `!=`,`<` 和 `>`) 2. **避免歧义**:确保重载运算符行为直观易懂 3. **资源管理**:赋值运算符需正确处理自赋值和资源释放 4. **返回值优化**: - 赋值运算符通常返回 `T&` 以支持链式调用 - 算术运算符通常返回新对象(值类型) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值