ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【C++学习总结2-6】类和对象(封装)—— 重载

2021-11-01 18:00:10  阅读:156  来源: 互联网

标签:封装 cout Point int C++ operator 重载 shared ptr


1. 函数重载

image-20210303131556097
编译器是没有办法通过返回值来确认调用的是哪个函数的。

代码:

#include<iostream>
using namespace std;

int func(int x) {
    return 2 * x;
}

double func(double x) {
    return x * x;
}

int func(int x, int y) {
    return x * y;
}

int main() {
    cout << func(2) << endl;//func(int)
    cout << func(2.3) << endl; // func(double)
    cout << func(2, 4) << endl; // func(int, int)
    return 0;
}

冲突形式:参数有默认值
image-20210303133045738
针对这种情况,可以将两个函数进行合并:

#include<iostream>
using namespace std;
//两种调用形式
//func(int)
//func(int, int)
int func(int x, int y = 10) {
    return x * y;
}
double func(double x) {
    return x * x;
}

int main() {
    cout << func(2) << endl;//func(int)
    cout << func(2.3) << endl; // func(double)
    cout << func(2, 4) << endl; // func(int, int)
    return 0;
}

无法通过返回值来做函数重载形式的区分:
image-20210303133430770

2. 重载的意义

image-20210303131723611

3. 友元

类外的一个函数 想要访问类内部成员,需要将该函数声明成类的一个友元函数。

形式如下:

class A {
	private :
    	int a;
    	int b;
    public :
    	A() : a(0), b(0) {}
    	A(int a, int b): a(a), b(b) {}
    	A(const A &obj): a(obj.a), b(obj.b) {}
    	friend A add(const A &obj1, const A &obj2);
};

A add(const A &obj1, const A &obj2) {
    A ret(0, 0);
    ret.a = obj1.a + obj2.a;
    ret.b = obj1.b + obj2.b;
    return ret;
}

实例:

#include<iostream>
using namespace std;

class Data {
public:
    Data() {}
    Data(int x, int y) : x(x), y(y) {
        cout << "Data : " << this << endl;
    }
    friend ostream &operator<<(ostream &out, const Data &d);
private:
    int x, y;
};

ostream &operator<<(ostream &out, const Data &d) {
    //访问Data的私有属性,需要在Data类中将该函数声明为friend
    out << d.x << " " << d.y;
    return out;
}

int main() {
    Data d(10, 9);
    //对<< 进行重载
    cout << d << endl;
    return 0;
}

友元函数本质上是一个类外部的函数,声明为友元函数后虽然还是类外的函数,但是可以访问类内部的私有属性。

4. 运算符重载(非成员)

image-20210303134715162

4.1 什么符号能被重载?

image-20210303134758397

sizeof也是运算符,也无法被重载,但是通常不被认为是运算符,而是函数。

注意:newdelete是运算符,malloc是函数。

4.2 类外重载

#include<iostream>
using namespace std;

class Point {
public:
    Point();
    Point(int x, int y);

private:
    friend Point operator+(const Point &a, const Point &b);
    friend ostream &operator<<(ostream &out, const Point &p);
    int x, y;
};

//委托构造:调用了Point(int, int)构造函数进行构造
Point::Point() : Point(0, 0) {}
Point::Point(int x, int y) : x(x), y(y) {}

//类外重载+号
//第一个参数代表+号左边的变量,第二个代表+号右边的变量
Point operator+(const Point &a, const Point &b) {
    Point c(a.x + b.x, a.y + b.y);
    return c;
}

//重载<<运算符
//第一个参数代表<<运算符左边的变量,第二个代表<<运算符右边的变量
ostream &operator<<(ostream &out, const Point &p) {
    out << "(" << p.x << ", " << p.y << ")";
    return out;
}

int main() {
    Point a(3, 4);
    Point b(7, 9);
    Point c = a + b;
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;
    return 0;
}
//输出结果:
//(3, 4)
//(7, 9)
//(10, 13)

问:什么是委托构造

答:

Point::Point() : x(0), y(0) {}
Point::Point(int x, int y) : x(x), y(y) {}

代码中的第2行是分别对 xy 进行赋值,第1行是将 xy 都赋值为0,所以1行可以委托2行进行构造:

Point::Point() : Point(0, 0) {}
Point::Point(int x, int y) : x(x), y(y) {}

4.3 类内重载

#include<iostream>
using namespace std;

class Point {
public:
    Point();
    Point(int x, int y);
    //类内重载运算符+,只需要传入一个参数
    //因为this指针指向的对象代表了+左边的参数,而传入的参数a代表+右边的参数
    Point operator+(const Point &a);
private:
    friend Point operator+(const Point &a, const Point &b);
    friend ostream &operator<<(ostream &out, const Point &p);
    int x, y;
};

Point::Point() : Point(0, 0) {}
Point::Point(int x, int y) : x(x), y(y) {}

//类内重载+
Point Point::operator+(const Point &a) {
    cout << "inner operator+" << endl;
    Point c(x + a.x, y + a.y);
    return c;
}

//类外重载+
Point operator+(const Point &a, const Point &b) {
    cout << "outer operator+" << endl;
    Point c(a.x + b.x, a.y + b.y);
    return c;
}

ostream &operator<<(ostream &out, const Point &p) {
    out << "(" << p.x << ", " << p.y << ")";
    return out;
}

int main() {
    Point a(3, 4);
    Point b(7, 9);
    Point c = a + b;
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;
    return 0;
}

类外重载和类内重载同时存在不会冲突,因为类内重载的优先级更高,同时存在的时候会调用类内重载。

4.4 重载成员函数的原则

  • 赋值(=)、下标([])、调用(())、成员访问(->) 运算符必须重载为成员函数
  • 复合赋值运算符一般重载为成员函数
  • 改变对象运算状态的运算符和类型密切相关的运算符,一般重载为成员函数,如:自增等
  • 具有对称性的运算符可能转换任意一端的对象,通常重载为非成员函数,如:相等,关系和位运算

4.5 重载+=运算符

#include<iostream>
using namespace std;

class Point {
public:
    Point();
    Point(int x, int y);
    //类内重载运算符+,只需要传入一个参数
    //因为this指针指向的对象代表了+左边的参数,而传入的参数a代表+右边的参数
    Point operator+(const Point &a);
    //重载+=运算符
    Point &operator+=(int);
private:
    friend Point operator+(const Point &a, const Point &b);
    friend ostream &operator<<(ostream &out, const Point &p);
    int x, y;
};

Point::Point() : Point(0, 0) {}
Point::Point(int x, int y) : x(x), y(y) {}

Point &Point::operator+=(int n) {
    x += n, y += n;
    return *this;
}

//类内重载+
Point Point::operator+(const Point &a) {
    cout << "inner operator+" << endl;
    Point c(x + a.x, y + a.y);
    return c;
}

//类外重载+
Point operator+(const Point &a, const Point &b) {
    cout << "outer operator+" << endl;
    Point c(a.x + b.x, a.y + b.y);
    return c;
}

ostream &operator<<(ostream &out, const Point &p) {
    out << "(" << p.x << ", " << p.y << ")";
    return out;
}

int main() {
    Point a(3, 4);
    Point b(7, 9);
    Point c = a + b;
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;

    a += 2; //给a的x和y各+2
    cout << a << endl;
    return 0;
}

注意这两行代码:

Point operator+(const Point &a);
Point &operator+=(int);

为什么重载 += 运算符返回的是引用?重载 + 运算符返回的是一个新的值?

a += 2; 是作用在 a 上。

从逻辑上来讲,这个表达式返回的还是 a 的值,所以返回引用;

从功能上来讲,如果连续加 (a += 2) += 2; 则必须返回引用,只有前一个 += 表达式返回的是引用,后一个 += 才会继续作用于对象 a 上。

运算符的返回值是任意的,并没有规定一定要返回引用。

4.6 [] 运算符的重载

[] 重载出来的对象叫做==数组对象==;

[]只支持==类内重载==

#include<iostream>
using namespace std;

class Point {
public:
    Point();
    Point(int x, int y);
    //类内重载运算符+,只需要传入一个参数
    //因为this指针指向的对象代表了+左边的参数,而传入的参数a代表+右边的参数
    Point operator+(const Point &a);
    //重载+=运算符
    Point &operator+=(int);
    int operator[](string s);
private:
    friend Point operator+(const Point &a, const Point &b);
    friend ostream &operator<<(ostream &out, const Point &p);
    int x, y;
};

Point::Point() : Point(0, 0) {}
Point::Point(int x, int y) : x(x), y(y) {}
int Point::operator[](string s) {
    if (s == "x") return x;
    if (s == "y") return y;
    return 0;
}
Point &Point::operator+=(int n) {
    x += n, y += n;
    return *this;
}

//类内重载+
Point Point::operator+(const Point &a) {
    cout << "inner operator+" << endl;
    Point c(x + a.x, y + a.y);
    return c;
}

//类外重载+
Point operator+(const Point &a, const Point &b) {
    cout << "outer operator+" << endl;
    Point c(a.x + b.x, a.y + b.y);
    return c;
}

ostream &operator<<(ostream &out, const Point &p) {
    out << "(" << p.x << ", " << p.y << ")";
    return out;
}

int main() {
    Point a(3, 4);
    Point b(7, 9);
    cout << a["x"] << endl;
    cout << a["y"] << endl;
    Point c = a + b;
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;

    a += 2; //给a的x和y各+2
    cout << a << endl;
    return 0;
}

因为 Point 类重载了 [] 运算符,所以所有 Point 类的对象都支持 [] 运算符,因此可以在 a 对象后面加上 [] 运算符。

a 对象的外在表现像一个数组,但是它的本质还是一个对象。所以将重载了 [] 运算符的类产生的对象,叫做数组对象,就是外在表现是一个数组,但是本质上还是一个对象。

4.7 () 运算符的重载

()重载出来的对象叫做函数对象,也叫==仿函数==;

#include<iostream>
using namespace std;

class ADD {
public :
    ADD(int c) : c(c) {}
    int operator()(int a, int b) {
        return a + b + c;
    }
private :
    int c;
};

int main() {
    ADD add(5);
    cout << add(6, 7) << endl; //输出18
    return 0;
}

add对象表现得像个函数,但是本质是个对象,所以叫做函数对象,也叫做可调用对象,也称仿函数

4.8 -> 运算符的重载

-> (间接引用)重载出来的对象叫做 指针对象

#include<iostream>
using namespace std;

class Point {
public :
    Point();
    Point(int x, int y);
    //类内重载运算符+,只需要传入一个参数
    //因为this指针指向的对象代表了+左边的参数,而传入的参数a代表+右边的参数
    Point operator+(const Point &a);
    //重载+=运算符
    Point &operator+=(int);
    //重载[]运算符
    int operator[](string s);
    int getX() { return x; }
    int getY() { return y; }
private :
    friend Point operator+(const Point &a, const Point &b);
    friend ostream &operator<<(ostream &out, const Point &p);
    int x, y;
};

class PPoint {
public :
    PPoint(Point *p) : p(p) {}
    Point *operator->() { return p; } //->运算符重载通常返回指针
private:
    Point *p;
};

Point::Point() : Point(0, 0) {}
Point::Point(int x, int y) : x(x), y(y) {}
int Point::operator[](string s) {
    if (s == "x") return x;
    if (s == "y") return y;
    return 0;
}
Point &Point::operator+=(int n) {
    x += n, y += n;
    return *this;
}

//类内重载+
Point Point::operator+(const Point &a) {
    cout << "inner operator+" << endl;
    Point c(x + a.x, y + a.y);
    return c;
}

//类外重载+
Point operator+(const Point &a, const Point &b) {
    cout << "outer operator+" << endl;
    Point c(a.x + b.x, a.y + b.y);
    return c;
}

ostream &operator<<(ostream &out, const Point &p) {
    out << "(" << p.x << ", " << p.y << ")";
    return out;
}

int main() {
    Point a(3, 4);
    Point b(7, 9);
    cout << a["x"] << endl;
    cout << a["y"] << endl;
    Point c = a + b;
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;

    a += 2; //给a的x和y各+2
    cout << a << endl;

    PPoint p = &a; //调用了转换构造函数
    cout << p->getX() << " " << p->getY() << endl;
    return 0;
}

对象 p 表现得像个指针,但是本质上是个对象,所以叫做对象指针

4.9 实现智能指针对象

智能指针前导知识

智能指针shared_ptr定义在头文件<memory>中。

产生了内存泄漏的代码:

#include <iostream>
#include <memory>
using namespace std;

class A {
public :
    A() {
        cout << "default constructor" << endl;
    }
    ~A() {
        cout << "destructor" << endl;
    }
};

int main() {
    A *p1 = new A();
    p1 = nullptr;
    return 0;
}

因为对象 p1 没有被销毁,系统中任何一个存储数据的地方都不知道对象的地址是什么,即一片存储区是属于当前进程的,但是当前进程永远找不到这片存储区在哪儿。

使用普通指针,只有构造的过程,没有析构的过程,所以发生了内存泄漏。

但是使用智能指针,不会产生内存泄漏:

#include <iostream>
#include <memory>
using namespace std;

class A {
public :
    A() {
        cout << "default constructor" << endl;
    }
    ~A() {
        cout << "destructor" << endl;
    }
};

int main() {
    A *p1 = new A();
    p1 = nullptr;

    //p2就是智能指针对象
    shared_ptr<A> p2(new A());
    p2 = nullptr; //自动析构

    return 0;
}

运行结果:

default constructor
default constructor
destructor

智能指针的智能之处:没有指针指向当前对象时,智能指针会将相关对象析构。

智能指针的原理:内部有个 引用计数,会记录指向当前对象的智能指针的数量。

#include <iostream>
#include <memory>
using namespace std;

class A {
public :
    A() {
        cout << "default constructor" << endl;
    }
    ~A() {
        cout << "destructor" << endl;
    }
};

int main() {
    A *p1 = new A();
    p1 = nullptr;

    //p2就是智能指针对象
    shared_ptr<A> p2(new A());
    //输出引用计数:p2所指向的对象有多少个指针指向它
    cout << p2.use_count() << endl; // 1,只有p2
    shared_ptr<A> p3 = p2;
    cout << p2.use_count() << endl; // 2,p2和p3
    p2 = nullptr; //自动析构
    cout << p3.use_count() << endl; // 1,只有p3

    return 0;
}

运行结果:

default constructor
default constructor
1
2
1
destructor

之所以最后调用 destructor,是因为在 main 函数执行完毕后,p3 对象被自动回收,指向当前对象的智能指针的数量就变成了0,引用计数变为了0,这时候对象就被智能指针析构了。

智能指针之所以表现得像个指针,是因为它重载了 -> 运算符,还重载了 * 运算符:

#include <iostream>
#include <memory>
using namespace std;

class A {
public :
    A() {
        cout << "default constructor" << endl;
    }
    int x, y;
    ~A() {
        cout << "destructor" << endl;
    }
};

int main() {
    A *p1 = new A();
    p1 = nullptr;

    //p2就是智能指针对象
    shared_ptr<A> p2(new A());
    //输出引用计数:p2所指向的对象有多少个指针指向它
    cout << p2.use_count() << endl; // 1
    shared_ptr<A> p3 = p2;
    p2->x = 123;
    p2->y = 456;
    (*p2).x = 456;
    cout << p2.use_count() << endl; // 2
    p2 = nullptr; //自动析构
    cout << p3.use_count() << endl; // 1

    return 0;
}

实现智能指针对象

#include <iostream>
#include <memory>
using namespace std;

namespace haizei {
class A {
public :
    A() {
        cout << "default constructor" << endl;
    }
    int x, y;
    ~A() {
        cout << "destructor" << endl;
    }
};
class shared_ptr {
public :
    shared_ptr();
    shared_ptr(A *);
    shared_ptr(const shared_ptr &);
    int use_count();
    A *operator->();
    A &operator*();
    //赋值运算符之所以要返回当前对象的引用,是为了支持连等的操作
    shared_ptr &operator=(const shared_ptr &);
    ~shared_ptr();
private :
    int *cnt; //引用计数
    A *obj;
};

shared_ptr::shared_ptr() : obj(nullptr), cnt(nullptr) {}

shared_ptr::shared_ptr(A *obj) : obj(obj), cnt(new int(1)) {}

shared_ptr::shared_ptr(const shared_ptr &p) : obj(p.obj), cnt(p.cnt) { *p.cnt += 1; }

int shared_ptr::use_count() { return cnt ? *cnt : 0; }

A *shared_ptr::operator->() { return obj; }

A &shared_ptr::operator*() { return *obj; }

shared_ptr::~shared_ptr() {
    if (cnt != nullptr) {
        *cnt -= 1;
        if (*cnt == 0) {
            delete obj;
            delete cnt;
        }
        obj = nullptr;
        cnt = nullptr;
    }
}

shared_ptr &shared_ptr::operator=(const shared_ptr &p) {
    //判断是否指向同一个对象
    if (this->obj != p.obj) {
        if (this->cnt != nullptr) {
            *(this->cnt) -= 1;
            if (*(this->cnt) == 0) {
                delete this->obj;
                delete this->cnt;
            }
        }
        this->obj = p.obj;
        this->cnt = p.cnt;
        if (this->cnt != nullptr) {
            *(this->cnt) += 1;
        }
    }
    return *this;
}

} // end of haizei


int main() {
    haizei::A *p1 = new haizei::A();
    p1 = nullptr;

    //p2就是智能指针对象
    haizei::shared_ptr p2(new haizei::A());
    cout << p2.use_count() << endl; // 1
    haizei::shared_ptr p3 = p2;
    p2->x = 123; p2->y = 456;
    (*p2).x = 456;
    cout << p2.use_count() << endl; // 2
    p2 = nullptr; //自动析构
    cout << p3.use_count() << endl; // 1
    p2 = p3;
    cout << p2.use_count() << endl; // 2
    return 0;
}

operator=函数的实现比较垃圾,所以更改为如下:

#include <iostream>
#include <memory>
using namespace std;

namespace haizei {
class A {
public :
    A() {
        cout << "default constructor" << endl;
    }
    int x, y;
    ~A() {
        cout << "destructor" << endl;
    }
};
class shared_ptr {
public :
    shared_ptr();
    shared_ptr(A *);
    shared_ptr(const shared_ptr &);
    int use_count();
    A *operator->();
    A &operator*();
    //赋值运算符之所以要返回当前对象的引用,是为了支持连等的操作
    shared_ptr &operator=(const shared_ptr &);
    ~shared_ptr();
private :
    void decrease_by_one();
    void increase_by_one();
    int *cnt; //引用计数
    A *obj;
};

shared_ptr::shared_ptr() : obj(nullptr), cnt(nullptr) {}

shared_ptr::shared_ptr(A *obj) : obj(obj), cnt(new int(1)) {}

shared_ptr::shared_ptr(const shared_ptr &p) : obj(p.obj), cnt(p.cnt) { increase_by_one(); }

int shared_ptr::use_count() { return cnt ? *cnt : 0; }

A *shared_ptr::operator->() { return obj; }

A &shared_ptr::operator*() { return *obj; }

void shared_ptr::decrease_by_one() {
    if (this->cnt != nullptr) {
        *(this->cnt) -= 1;
        if (*(this->cnt) == 0) {
            delete this->obj;
            delete this->cnt;
        }
    }
    return ;
}

void shared_ptr::increase_by_one() {
    if (cnt != nullptr) {
        *cnt += 1; //cnt[0] += 1;
    }
    return ;
}

shared_ptr::~shared_ptr() {
    this->decrease_by_one();
    this->obj = nullptr;
    this->cnt = nullptr;
}

shared_ptr &shared_ptr::operator=(const shared_ptr &p) {
    //判断是否指向同一个对象
    if (this->obj != p.obj) {
        decrease_by_one(); //引用计数-1
        //拷贝对象
        obj = p.obj;
        cnt = p.cnt;
        increase_by_one(); //给新的引用计数+1
    }
    return *this;
}

} // end of haizei


int main() {
    haizei::A *p1 = new haizei::A();
    p1 = nullptr;

    //p2就是智能指针对象
    haizei::shared_ptr p2(new haizei::A());
    cout << p2.use_count() << endl; // 1
    haizei::shared_ptr p3 = p2;
    p2->x = 123; p2->y = 456;
    (*p2).x = 456;
    cout << p2.use_count() << endl; // 2
    p2 = nullptr; //自动析构
    cout << p3.use_count() << endl; // 1
    p2 = p3;
    cout << p2.use_count() << endl; // 2
    return 0;
}

运行结果:

default constructor
default constructor
1
2
1
2
destructor

至此,完成了简单的智能指针的实现。

4.10 调用对象

对数组进行排序:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

ostream &operator<<(ostream &out, const vector<int> &a) {
    for (auto x : a) {
        out << x << " ";
    }
    return out;
}

int main() {
    vector<int> arr;
    int n;
    cin >> n;
    while (n--) { int a; cin >> a, arr.push_back(a); }
    sort(arr.begin(), arr.end());
    cout << arr << endl;
    return 0;
}

sort函数默认是从小到大排序。如果想从大到小排序,一般是添加自定义一个比较函数:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

ostream &operator<<(ostream &out, const vector<int> &a) {
    for (auto x : a) {
        out << x << " ";
    }
    return out;
}

bool cmp1(int a, int b) {
    return a > b; //当a > b的时候,a排在b前面,也就是从大到小排序
}

int main() {
    vector<int> arr;
    int n;
    cin >> n;
    while (n--) { int a; cin >> a, arr.push_back(a); }
    sort(arr.begin(), arr.end(), cmp1);
    cout << arr << endl;
    return 0;
}

在学习了 仿函数 后,也可以使用 仿函数 来实现自定义比较规则:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

ostream &operator<<(ostream &out, const vector<int> &a) {
    for (auto x : a) {
        out << x << " ";
    }
    return out;
}

bool cmp1(int a, int b) {
    return a > b; //当a > b的时候,a排在b前面,也就是从大到小排序
}

class CMP {
public :
    bool operator()(int a, int b) {
        return a > b;
    }
};

int main() {
    vector<int> arr;
    int n;
    cin >> n;
    while (n--) { int a; cin >> a, arr.push_back(a); }
    //sort(arr.begin(), arr.end(), cmp1);
    sort(arr.begin(), arr.end(), CMP());//CMP()构造函数构造了一个匿名对象,第三个位置放置的应该是函数名,而仿函数的函数名就是对象名
    cout << arr << endl;
    return 0;
}

仿函数的功能是由重载的()运算符来决定的。

上面还可以改写为如下:

CMP cmp2;
sort(arr.begin(), arr.end(), cmp2);

仿函数比普通函数的功能更强大:根据z值的不同,使用不同的比较规则

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

ostream &operator<<(ostream &out, const vector<int> &a) {
    for (auto x : a) {
        out << x << " ";
    }
    return out;
}

bool cmp1(int a, int b) {
    return a > b; //当a > b的时候,a排在b前面,也就是从大到小排序
}

class CMP {
public :
    CMP(int z = 0) : z(z) {} //z = 0 less, z = 1 greater
    bool operator()(int a, int b) {
        return (a < b) ^ !!(z);
    }
    int z;
};

int main() {
    vector<int> arr;
    int n;
    cin >> n;
    while (n--) { int a; cin >> a, arr.push_back(a); }
    sort(arr.begin(), arr.end(), CMP());//CMP()就是一个匿名对象,第三个位置放置的应该是函数名,而仿函数的函数名就是对象名
    cout << arr << endl;
    return 0;
}

sort(arr.begin(), arr.end(), CMP()); 的是默认的情况,是从小到大排序;而sort(arr.begin(), arr.end(), CMP(1));就是从大到小排。

4.11 实现自己的 sort 函数

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

ostream &operator<<(ostream &out, const vector<int> &a) {
    for (auto x : a) {
        out << x << " ";
    }
    return out;
}

bool cmp1(int a, int b) {
    return a > b; //当a > b的时候,a排在b前面,也就是从大到小排序
}

namespace haizei {

class CMP {
public :
    CMP(int z = 0) : z(z) {} //z = 0 less, z = 1 greater
    bool operator()(int a, int b) {
        return (a < b) ^ !!(z);
    }
    int z;
};

//cmp是一个函数指针对象,本质是对象,表现得像个函数指针,返回值是bool,传入参数是两个int
void sort(int *arr, int l, int r, function<bool(int, int)> cmp = CMP()) {
    //就是快速排序
    if (l >= r) return ;
    int x = l, y = r, z = arr[(l + r) >> 1];
    do {
        while (cmp(arr[x], z)) ++x;
        while (cmp(z, arr[y])) --y;
        if (x <= y) {
            swap(arr[x], arr[y]);
            ++x, --y;
        }
    } while (x <= y);
    sort(arr, l, y, cmp);
    sort(arr, x, r, cmp);
    return ;
}

}; //end of haizei

int main() {
    vector<int> arr;
    int n;
    cin >> n;
    while (n--) { int a; cin >> a, arr.push_back(a); }
    //sort(arr.begin(), arr.end(), cmp1);
    sort(arr.begin(), arr.end(), haizei::CMP());//CMP()就是一个匿名对象,第三个位置放置的应该是函数名,而仿函数的函数名就是对象名
    cout << arr << endl;


    // ====使用自己写的sort函数
    int arr2[5] = {6, 8, 4, 5, 1};

    haizei::sort(arr2, 0, 4); //默认情况从小到大排
    for (int i = 0; i < 5; i++) {
        cout << arr2[i] << " ";
    }
    cout << endl;

    //从大到小排: 使用自定义函数
    haizei::sort(arr2, 0, 4, cmp1);
    for (int i = 0; i < 5; i++) {
        cout << arr2[i] << " ";
    }
    cout << endl;

    haizei::sort(arr2, 0, 4); //默认情况从小到大排
    for (int i = 0; i < 5; i++) {
        cout << arr2[i] << " ";
    }
    cout << endl;

    //从大到小排: 使用仿函数
    haizei::sort(arr2, 0, 4, haizei::CMP(1));
    for (int i = 0; i < 5; i++) {
        cout << arr2[i] << " ";
    }
    cout << endl;

    return 0;
}

运行结果:

5  #输入
1 4 2 0 9 #输入
0 1 2 4 9 #输出
1 4 5 6 8 #输出
8 6 5 4 1 #输出
1 4 5 6 8 #输出
8 6 5 4 1 #输出

系统 sort 函数之所以能传入可调用对象,是因为使用了function这个模板类。

标签:封装,cout,Point,int,C++,operator,重载,shared,ptr
来源: https://blog.csdn.net/u011386173/article/details/121084758

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有