美文网首页
C++ Operators 操作符重载

C++ Operators 操作符重载

作者: 坚果jimbowhy | 来源:发表于2020-07-17 07:38 被阅读0次
    C++ Operators

    参考代码仓库:https://github.com/jimboyeah/demo/blob/cppDemos/src/operators.cpp

    operators 运算符重载

    C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。

    在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的参数列表必须不同,但不能仅通过返回类型的差别来重载函数

    操作符重载方式有三种,类成员函数、友元函数、全局函数。使用类成员函数实现操作符重载,其函数列表中隐含了第二参数为 this 指针,不在参数列表中编写出来。如果使用码友元函数或全局函数,则需要在参数列表中增加这个隐含的参数,增加的这个参数可以用来代替 this 指针。

    运算符重载 5 种基本类型:

    • overloaded operator;
    • user-defined conversion function;
    • allocation function;
    • deallocation function;
    • user-defined literal.

    罗列如下:

    operator op
    
    operator type
    
    operator new
    operator new []
    
    operator delete
    operator delete []  
    
    operator "" suffix-identifier (since C++11) 
    

    其中 op 可以以下 38 个操作符号之一:

    + - * / % ˆ & | ~ ! = < > += -= *= /= %= ˆ= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* -> ( ) [ ] 
    

    其中 operator 是运算符重载关键字,事实上可以将运算符重载当作函数来看待,即每个重载的运算就是一个对应的函数。

    表达式 作为成员函数 作为非成员函数 示例
    @a (a).operator@( ) operator@(a) !cin 等价 cin.operator!()
    a@b (a).operator@(b) operator@(a, b) cout << 42 等价 cout.operator<<(42)
    a=b (a).operator=(b) 不可用 string s; s = "abc"; 等价 s.operator=("abc")
    a(b...) (a).operator()(b...) 不可用 random_device r; auto n = r(); 等价 r.operator()()
    a[b] (a).operator 不可用 map<int, int> m; m[1] = 2; 等价 m.operator
    a-> (a).operator->( ) 不可用 auto p = make_unique<S>(); p->bar() 等价 p.operator->()
    a@ (a).operator@(0) operator@(a, 0) vector<int>::iterator i = v.begin(); i++ 等价 i.operator++(0)

    此表中,@ 是所有匹配运算符的占位符号:

    • 前缀运算符即是 @a;
    • 后缀运算符即是 a@,除 -> 外;
    • 中间点位的运算符即是 a@b,除 = 外;

    除内置运算符,built-in operators,重载运算符都可以用函数式调用:

    std::string str = "Hello, ";
    str.operator+=("world");                       // same as str += "world";
    operator<<(operator<<(std::cout, str) , '\n'); // same as std::cout << str << '\n';
                                                   // (since C++17) except for sequencing
    

    在 C++ 中,标准库本身对左移运算符 << 和右移运算符 >> 进行了重载,使其能够用于不同数据的输入输出,但是输入输出的对象只能是 C++ 内置的数据类型,例如 bool、int、double 和标准库所包含的类类型,例如 string、complex、ofstream、ifstream 等。

    习惯上,输入输出运算符号是 cin >> 和 cout << 这样使用的,实现自己的输入输出运算符的重载,通常使用友元函数的方式来实现,如果使用成员函数来重载会出现 obj << cout; 这种不自然的代码。

    示范实现 <<、>>、[] 以及 () 强制类型转换运算符重载:

    #include <string>
    #include <cstdarg>
    #include <iostream>
    
    using namespace std;
    
    /*-------------------------------*/
    // Header            
    /*-------------------------------*/
    class Base
    {
    public:
        const char * text = "Test content...";
        Base(const char *);
        void operator=(Base &b);
        const char & operator[](int) const;
        friend ostream & operator<<(basic_ostream<char> &out, Base & b);
        ostream & operator<<(basic_ostream<char> &out);
        operator const char *(); // 重载强制类型转换运算符
    };
    
    
    /*-------------------------------*/
    // Implementation            
    /*-------------------------------*/
    Base::Base(const char * value)
    {
        this->text = value;
    }
    
    void Base::operator=(Base &b)
    {
        this->text = b.text;
    }
    
    Base::operator const char *()
    {
        return this->text;
    }
    
    const char & Base::operator[](int index) const
    {
        return this->text[index];
    }
    
    // The problem is that you define it inside the class, which
    // a) means the second argument is implicit (this) and
    // b) it will not do what you want it do, namely extend std::ostream.
    ostream & Base::operator<<(basic_ostream<char> &out)
    {
        return out << "Base.text = " << this->text;
    }
    
    
    ostream & operator<<(basic_ostream<char> &out, Base & b)
    {
        return out << "Base.text = " << b.text;
    }
    
    
    int main(int argc, char *argv[])
    {
        Base a{"Some text..."};
        Base b{"More text..."};
        b = a;
        std::cout << "after operator<< : " << a << std::endl;
        std::cout << "after operator = : " << b << std::endl;
        std::cout << "after operator[1]: " << b[1] << std::endl;
        a << std::cout << " <--- use operator << as member function" << endl;
        std::cout << "after typecast: " << (const char *)b << endl;
        std::cout << "another typecast: " << b.operator const char *() << endl;
    }
    

    另外,注意一下 operator<< 如果以成员函数的方式实现,这样做的话,表示需要通过成员函数调用的方式来使用输出操作符,也就是要在 << 的左侧写类实例。

    展示了强制类型转换运算符的两种方式,一种是以 C 风格的类型转换,另一种是成员函数方式的类型转换,语法看起来真的很怪诞!

    相关文章

      网友评论

          本文标题:C++ Operators 操作符重载

          本文链接:https://www.haomeiwen.com/subject/azlwhktx.html