CPP-operator==, <overloading

C++ 中的运算符重载:==, !=, < 和相关实现
这篇博客探讨了在C++中如何利用已有的运算符重载来实现其他相关操作符。一旦定义了`operator==`,可以轻松实现`operator!=`,只需调用`operator==`并取反。同样,定义了`<`后,可以方便地定义`>`。标准库提供了一些模板帮助实现这些关系操作符。文章通过为数组类型定义`<`运算符为例,展示了如何实现这些操作,并提到了在成员函数中使用`this`指针的细节。然而,在尝试使用非常量成员函数(如lengthsquare())时,由于`operator<`是常量成员函数,导致了编译错误。

如果已经定义了operator==,那么operator!=很容易实现,只要调用operator==,然后取反。

bool Array::operator!=(const Array& v) const
{
    return !((*this) == v);
}

这个函数的形式实际上和具体的类无关。即如果定义了operator==,那么总能根据这个模式定义operatot!=. 同样,如果定义了<, 则很容易能够定义>. 如果定义了==,则结合<和==,则能够定义<=和>=. 标准文件util包含了一系列预先定义的这些关系操作符的模式。使用时只需定义operator==, operator<,则自动有operator!=, operator>, operator<=.因此从不需要定义多余两个比较操作符。看以下例子:为array定义<.

bool operator< (const Array& v) const;

实现:

bool Array::operator< (const Array& v) const
{
    int n; //the length of the shortest of this object and v
    if(num <v.num)
    n = num;
    else
    n = v.num;
    for(int i=0;i<n;i++)
    if(p[i] <v.p[i])
    return true;
    else if(p[i]>v.p[i])
    return false;
    return num <v.num; //equal length
}

为了自动使用别的比较操作符。需要在类定义文件中包含以下信息:

#include〈utility>
using namespace std::rel_ops;

单操作符:operator-

Array operator- () const;

Array Array::operator- () const
{
Array temp(*this); //creat a copy of this array object
for(int i=0;i

class Myclass{
public:
    bool operator== (const Myclass &vb) const {
            if(this->vx == vb.vx && this->vy == vb.vy && this->vz == vb.vz) return true;
            else return false;};
private:
    double  vx,vy,vz;
}

其实当在一个成员函数内部写一个成员名字时候(如vx),编译器将解释为this->vx。因此以上语句其实不需要明确指出this->vx;故代码可以简化:

class Myclass{
public:
    bool operator== (const Myclass &vb) const {
        return(vx == vb.vx && vy == vb.vy && vz == vb.vz) };
private:
    double  vx,vy,vz;
}

接下来实现矢量大小比较(长度)

bool operator<  (const Vector3d &vb) const {return (this->lengthsquare() < vb.lengthsquare());};

inline double lengthsquare() {return(vx*vx + vy*vy + vz*vz);};

这几句总是给错误提示:
“the object has type qualifiers that are not compatible with the member function”,

因为operator< 声明为一个常函数,而函数lengthsquare()没有声明为常函数。

bool operator<  (const Vector3d &vb) const {return (this->lengthsquare() < vb.lengthsquare());};

inline double lengthsquare() const{return(vx*vx + vy*vy + vz*vz);};

其他comparison operator:

bool operator== (const Vector3d &vb) const {return(vx == vb.vx && vy == vb.vy && vz == vb.vz);}
        bool operator!= (const Vector3d &vb) const {return !(*this == vb);};
        bool operator<  (const Vector3d &vb) const {return (this->lengthsquare() < vb.lengthsquare());};
        bool operator>= (const Vector3d &vb) const {return !(*this < vb);};
        bool operator>  (const Vector3d &vb) const {return (*this >= vb) && (*this != vb);};
        bool operator<= (const Vector3d &vb) const {return !(*this > vb);};
// Fig. 11.9: String.h // String class definition with operator overloading. #ifndef STRING_H #define STRING_H #include <iostream> using namespace std; class String { friend ostream &operator<<( ostream &, const String & ); friend istream &operator>>( istream &, String & ); public: String( const char * = "" ); // conversion/default constructor String( const String & ); // copy constructor ~String(); // destructor const String &operator=( const String & ); // assignment operator const String &operator+=( const String & ); // concatenation operator bool operator!() const; // is String empty? bool operator==( const String & ) const; // test s1 == s2 bool operator<( const String & ) const; // test s1 < s2 // test s1 != s2 bool operator!=( const String &right ) const { return !( *this == right ); } // end function operator!= // test s1 > s2 bool operator>( const String &right ) const { return right < *this; } // end function operator> // test s1 <= s2 bool operator<=( const String &right ) const { return !( right < *this ); } // end function operator <= // test s1 >= s2 bool operator>=( const String &right ) const { return !( *this < right ); } // end function operator>= char &operator[]( int ); // subscript operator (modifiable lvalue) char operator[]( int ) const; // subscript operator (rvalue) String operator()( int, int = 0 ) const; // return a substring int getLength() const; // return string length private: int length; // string length (not counting null terminator) char *sPtr; // pointer to start of pointer-based string void setString( const char * ); // utility function }; // end class String #endif
最新发布
11-13
// Fig. 11.9: String.h // String class definition with operator overloading. --- ### 题目重述 请根据提供的 `String` 类定义,实现能够重载加号(`+`)运算符的功能,使得两个 `String` 对象可以进行拼接操作而不修改原对象,支持如下语句: ```cpp string1 = string2 + string3; ``` 同时,在已有类结构基础上补充必要的函数原型与实现思路。 --- ### 给出答案(答案为带注释的代码块) ```cpp // 在 String 类中添加 operator+ 的声明(建议放在 public 区域) const String operator+( const String & ) const; // 返回一个新的 String 对象,不改变原对象 // 实现示例(可在类外定义) const String String::operator+( const String &right ) const { // 创建新字符数组,长度为两字符串之和 + 1(含 '\0') char *temp = new char[length + right.length + 1]; // 复制当前对象的字符串 strcpy( temp, sPtr ); // 拼接右侧字符串 strcat( temp, right.sPtr ); // 构造新的 String 对象并返回 String result( temp ); delete[] temp; // 避免内存泄漏(注意:此处 temp 内容已被复制) return result; } ``` > ⚠️ 注意:上面 `delete[] temp;` 是否保留取决于构造函数是否立即复制了数据。若 `String(const char*)` 构造函数会再次深拷贝 `temp` 中的内容,则此处可安全释放。 更稳妥写法(推荐): ```cpp const String String::operator+( const String &right ) const { char *temp = new char[length + right.length + 1]; strcpy(temp, sPtr); strcat(temp, right.sPtr); String result(temp); // result 自己负责管理自己的内存 delete[] temp; // 可以删除,因为 result 已完成复制 return result; } ``` 或进一步优化使用 RAII: ```cpp const String String::operator+( const String &right ) const { size_t newLen = length + right.length; char *temp = new char[newLen + 1]; // 动态分配临时缓冲区 strcpy(temp, sPtr); strcpy(temp + length, right.sPtr); // 更高效代替 strcat temp[newLen] = '\0'; String result(temp); delete[] temp; return result; } ``` --- ### 代码解析 1. **函数签名**:`const String operator+( const String & ) const;` - 声明为 `const` 成员函数,保证当前对象不被修改。 - 返回值是 `String` 类型(非引用),因为结果是一个新对象。 - 参数以 `const &` 形式传入,避免复制开销。 2. **内存管理**: - 使用 `new[]` 分配足够空间用于存储拼接后的字符串。 - 调用 `strcpy` 和 `strcat`(或手动复制)完成拼接。 - 利用已有的构造函数 `String(const char*)` 将拼接好的 C 字符串封装成新 `String` 对象。 3. **返回机制**: - 返回的是局部对象的副本(通过拷贝构造函数),编译器通常会优化(RVO/NRVO)。 4. **安全性**: - 所有动态分配的中间内存都及时释放,防止内存泄漏。 --- ### 知识点(列出该代码中遇到的知识点) - **运算符重载**:允许自定义类的对象使用内置运算符(如 `+`),提升代码可读性。必须保持语义一致。 - **常量成员函数**:用 `const` 修饰成员函数,表明其不会修改调用对象的状态,适用于比较、访问、组合等场景。 - **深拷贝与资源管理**:当类管理动态资源(如 `char*`)时,需正确实现构造函数、析构函数和赋值操作,防止内存错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值