美文网首页
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://github.com/jimboyeah/demo/blob/cppDemos/sr...

  • Dart(2.2) - 操作符(Operators)

    操作符(Operators) 下表是Dart中定义的操作符。 很多操作符都可以重载,详情参考Overridable...

  • Kotlin --- Operator Overloading

    简述 Kotlin的操作符重载与C++类似,虽然没有C++那么强大,但是仍然可以实现Kotlin的操作符重载。 操...

  • C++基础-(重载)

    C++基础 重载 哪些运算符可以被重载:::,.,->,*,?:不能被重载 重载操作符的标志(operator) ...

  • C++中的操作符重载

    操作符重载 C++中的重载能够扩展操作符的功能 操作符的重载以函数的方式进行 本质:用特殊形式的函数扩展操作符的功...

  • C++学习笔记(七)操作符重载(上)

    1、基本操作符重载 操作符重载指的是将C++提供的操作符进行重新定义,使之满足我们所需要的一些功能。 在C++中可...

  • C++ 操作符重载

    操作符重载 操作符的重载是在实际的C++编程过程中不太容易引人注意但却非常实用的一个特性。合理的实现操作符重载可以...

  • 《C++ Primer Plus》第11章学习笔记

    内容思维导图 1. 操作符重载 操作符重载(Operator overloading)是一种形式的C++多态。第8...

  • 1.2.20_C++ 下标运算符 [] 重载

    C++ 重载运算符和重载函数 下标操作符 [] 通常用于访问数组元素。重载该运算符用于增强操作 C++ 数组的功能...

  • Geekband C++ 第五周

    概述 C++模板简介 函数模板 C++类模板 操作符重载 泛型编程 容器

网友评论

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

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