C++类与运算符重载详解
立即解锁
发布时间: 2025-08-20 01:48:56 阅读量: 2 订阅数: 3 


懒惰程序员的C++入门指南
### C++ 类与运算符重载详解
#### 1. 静态成员与 Car 类
在 C++ 编程中,我们有时需要跟踪某个类的对象数量。以二手车交易为例,我们可以创建一个 `Car` 类来实现这个功能。
```cpp
//Class Car, and a program to use it
#ifndef CAR_H
#define CAR_H
#include <iostream>
class Car
{
public:
enum { MAX_NAME_SIZE = 50 };
Car();
Car(const Car &);
Car(int theYear, const char* theMake, const char* theModel);
void print(std::ostream&) const;
const char* make () const { return make_; }
const char* model() const { return model_; }
int year () const { return year_; }
static int numCars() { return numCars_;}
void buy () { ++numCars_; }
void sell () { --numCars_; }
private:
char make_[MAX_NAME_SIZE], model_[MAX_NAME_SIZE];
int year_;
static int numCars_;
};
#endif //CAR_H
```
在这个类中,`numCars_` 是一个静态数据成员,用于记录当前库存的汽车数量。静态成员属于整个类,而不是某个特定的对象。`numCars()` 是一个静态成员函数,用于获取当前汽车的数量。
需要注意的是,静态成员函数不能被声明为 `const`。另外,静态数据成员不能在类定义中初始化,需要在类外部进行初始化。以下是 `car.cpp` 文件中的初始化代码:
```cpp
//Class Car
#include <cstring>
#include "car.h"
int Car::numCars_ = 0; //initialize the number of Cars to 0
```
下面是一个使用 `Car` 类的示例程序:
```cpp
//A program that uses the Car class
#include "car.h"
using namespace std;
int main ()
{
Car banzai (2020, "Ford", "GT40");
Car mudbug (1987, "Jeep", "Wrangler");
Car sport (2000, "Toyota", "Corolla");
cout << "Looks like we have "
<< Car::numCars () << " cars in stock!" << endl;
return 0;
}
```
这个程序创建了三辆汽车对象,并输出当前库存的汽车数量。
#### 2. 字符串类与运算符重载
在 C++ 中,数组的 `==` 运算符比较的是内存地址,而不是数组的内容。例如:
```cpp
char string1[] = "Hello", string2[] = "Hello";
if (string1 == string2) ...
```
这个条件会失败,因为 `string1` 和 `string2` 的内存地址不同。为了解决这个问题,我们可以创建自己的字符串类,并重载运算符。
以下是一个基本的字符串类 `String` 的定义:
```cpp
class String
{
public:
String (const char* other=""); //conversion from char* ctor;
// default ctor
String (const String &other);
private:
char* contents_;
};
```
为了处理任意长度的字符串,我们使用动态内存分配。在构造函数中,我们可以选择将 `contents_` 初始化为 `nullptr` 或空字符串 `""`。这里我们选择将其初始化为空字符串。
```cpp
String::String (const char* other = "")
{
contents_ = new char[strlen(other) + 1];
//The +1 is room for final '\0'
strcpy(contents_, other);
}
String::String (const String &other)
{
contents_ = new char[strlen(other.contents_) + 1];
strcpy(contents_, other.contents_);
}
```
为了减少代码冗余,我们可以使用委托构造函数:
```cpp
String (const String &other) : String (other.c_str()) {}
```
同时,我们可以添加一些新的成员函数:
```cpp
const char* c_str() const { return contents_; }
int size () const { return (int) strlen (c_str()); }
```
#### 3. 析构函数
当使用动态分配的数组时,我们需要在对象销毁时释放内存。这可以通过析构函数来实现。
```cpp
String::~String () { if (contents_) delete [] contents_; }
```
析构函数的名称是类名前加上 `~`,它会在对象销毁时自动调用。这里的 `if (contents_)` 是为了避免删除 `nullptr` 导致的崩溃。
#### 4. 运算符重载
我们可以重载各种运算符,让它们按照我们的需求工作。以下是一些常见运算符的重载示例:
##### 4.1 比较运算符
```cpp
bool String::operator== (const String& other) const
{
return strcmp (c_str(), other.c_str()) == 0;
}
bool String::operator!= (const String& other) const
{
return ! (*this == other);
}
```
`operator==` 用于比较两个字符串的内容是否相等,`operator!=` 则是 `operator==` 的取反。
##### 4.2 一元运算符
```cpp
bool String::operator! () const { return ! size(); }
```
`operator!` 用于判断字符串是否为空。
##### 4.3 赋值运算符
```cpp
const String& String::operator= (const String& other)
{
if (contents_) delete[] contents_; //delete old memory
contents_ = new char[strlen(other.c_str()) + 1]; //get new memory
//The +1 is room for final '\0'
strcpy(contents_, other.c_str()); //copy contents over
return *this;
}
```
赋值运算符 `operator=` 需要返回 `*this`,表示当前对象。为了提高效率,我们通常返回一个常量引用。
##### 4.4 算术运算符
```cpp
const String& String::operator+= (const String& other)
{
char* oldContents = contents_;
contents_ = new char [size() + other.size() + 1];
//1 extra space at the end for the null char
strcpy (contents_, oldContents); //copy old into new
strcat (contents_, other.c_str());//append other contents
delete [] oldContents;
return *this;
}
String String::operator+ (const String& other) const
{
String result = *this; result += other; return result;
}
```
`operator+=` 用于字符串的拼接,`operator+` 则是返回一个新的拼接后的字符串。需要注意的是,`operator+` 不能返回常量引用,因为返回的是一个局部变量。
##### 4.5 下标运算符
```cpp
char String::operator[] (int index) const { return contents_[index]; }
char& String::operator[] (int index) { return contents_[index]; }
```
下标运算符 `operator[]` 需要提供两个版本,一个是常量版本,用于只读访问;另一个是非常量版本,用于可写访问。
###
0
0
复制全文
相关推荐








