1.全局函数和类成员函数转化

全局函数和成员函数的相互转化:只需要修改一个指向本类的this指针;

#include <iostream>
using namespace std;class Test
{
public:Test(int a, int b){this->a = a;this->b = b;}//成员函数Test &Gadd2(Test &t2){this->a = this->a + t2.a;this->b = this->b + t2.b;return *this;}
public:int a;int b;
};
//全局函数
Test &Gadd1(Test &t1, Test &t2)
{Test t3(0, 0);t3.a = t1.a + t2.a;t3.b = t1.b + t2.b;return t3;
}//从成员函数转化为全局函数 只需要加一个 this指针(指向本类的类指针)
//从全局函数转化为类的成员函数是,需要减一个做左操作数参数
void main()
{Test t1(1, 2), t2(3, 4);//Test t3 = Gadd1(t1, t2);t1.Gadd2(t2);system("pause");
}

2.友元

2.1友元函数

#include "iostream"
using namespace std;
class Test2
{
public://友元函数的特点是:有一个参数是友元类的指针或引用friend int OpMem(Test2 *p, int a); //友元函数Test2(int a, int b){this->a = a;this->b = b;}int getA(){return this->a;}
protected:
private:int a;int b;
};
int OpMem(Test2 *p, int a)
{p->a = a;return 0;
}
void main()
{Test2 t1(1, 2);t1.getA();//没有friend的情况下,如果获取对象t1的私有数据,需要用get方法。OpMem(&t1, 10);system("pause");
}

2.2友元类

#include <iostream>
using namespace std;class A
{friend class B;//B是A的友元类
public:void  Display() { cout << x << endl; };
private:int  x;
};
//设计模式中的组合场景。表象是设置b100, 本质上是修改a的数据。
class  B
{
public:void Set(int i) { Aobject.x = i; }void Display()  { Aobject.Display(); }
private:A  Aobject;
};void main()
{B  Bobject;Bobject.Set(100);Bobject.Display();system("pause");
}

3.操作符重载

C++有许多内置的数据类型,包括int,char,double等,每一种类型都有许多运算符,例如加,减,乘,除等。当用户定义了类的对象时,两个对象之间是不能进行这些操作的,比如hyong类的对象a+b,这样的语句如果没有重载+运算符就会出错。但C++允许用户把这些运算符添加到自已的类中以方便类对象之间的运算就像内置类型的运算一样方便,比如对象a+b这样就很明白更容易懂,当然也可以在类中定义一个对象间相加的函数,比如a.add(b)调用函数add()以实现两个对象a和b相加,但是这条语句没有比a+b更容易让人理解。

3.1通过友元函数实现操作符重载,

#include <iostream>
using namespace std;
class Fushu
{
private:int a;int b;//通过友元函数实现+操作friend Fushu operator+(Fushu &c1, Fushu &c2);
public:Fushu(int a=0, int b=0){this->a = a;this->b = b;}void print(){cout << a << "+" << b << "i" << endl;}
};
Fushu operator+(Fushu &c1, Fushu &c2)
{Fushu tmp;tmp.a = c1.a + c2.a;tmp.b = c1.b + c2.b;return tmp;
}
void main()
{Fushu c1(1, 2), c2(3, 4);Fushu c3 = c1+c2;c3.print();system("pause");
}
#include <iostream>
using namespace std;
class Fushu
{
private:int a;int b;//通过友元函数实现前++操作friend Fushu &operator++(Fushu &c2);
public:Fushu(int a=0, int b=0){this->a = a;this->b = b;}void print(){cout << a << "+" << b << "i" << endl;}
};
Fushu &operator++(Fushu &c2)
{c2.a++;c2.b++;return c2;
}
void main()
{Fushu c1(1, 2), c2(3, 4);++c2;c2.print();system("pause");
}

3.2通过类的成员函数实现操作符重载

#include <iostream>
using namespace std;
class Fushu
{
private:int a;int b;//通过友元函数实现+操作friend Fushu operator+(Fushu &c1, Fushu &c2);
public://通过类的成员函数实现-操作Fushu operator-(Fushu &c2){Fushu tmp;tmp.a = this->a - c2.a;tmp.b = b - c2.b;//此处的this可以省略return tmp;}
public:Fushu(int a=0, int b=0){this->a = a;this->b = b;}void print(){cout << a << "+" << b << "i" << endl;}
};
Fushu operator+(Fushu &c1, Fushu &c2)
{Fushu tmp;tmp.a = c1.a + c2.a;tmp.b = c1.b + c2.b;return tmp;
}
void main()
{Fushu c1(1, 2), c2(3, 4);Fushu c3 = c1+c2;//operator+(c1,c2);c3.print();
//目标 通过类的成员函数,完成操作符重载
//1 要承认操作符重载是一个函数,要写函数原型
//2 写出函数调用语言 c1.operator-(c2)
//3 完善函数原型   Fushu c4 = c1 - c2;//operator-(c1,c2) -->c1.operator-(c2)-->Fushu operator-(Fushu &c2);c4.print();system("pause");
}
#include <iostream>
using namespace std;
class Fushu
{
private:int a;int b;//通过友元函数实现前++操作friend Fushu &operator++(Fushu &c2);
public:Fushu(int a=0, int b=0){this->a = a;this->b = b;}void print(){cout << a << "+" << b << "i" << endl;}
public://通过类的成员函数实现前--操作Fushu& operator--(){this->a--;this->b--;return *this;}
};
Fushu &operator++(Fushu &c2)
{c2.a++;c2.b++;return c2;
}
void main()
{Fushu c1(1, 2), c2(3, 4);//通过友元函数实现前++操作++c2;    c2.print();//通过类的成员函数实现前--操作--c2;    c2.print();system("pause");
}

综合:

#include <iostream>
using namespace std;class Fushu
{
private:int a;int b;//通过友元函数实现前++操作friend Fushu &operator++(Fushu &c2);//通过友元函数实现后++操作friend Fushu operator++(Fushu &c2, int);//用缺省参数占位,跟前++区分
public:Fushu(int a=0, int b=0){this->a = a;this->b = b;}void print(){cout << a << "+" << b << "i" << endl;}
public://通过类的成员函数实现前--操作Fushu& operator--(){this->a--;this->b--;return *this;}//通过类的成员函数实现前--操作Fushu& operator--(int)//用缺省参数占位,跟后--区分{Fushu tmp;tmp = *this;this->a--;this->b--;return tmp;}
};Fushu &operator++(Fushu &c2)
{c2.a++;c2.b++;return c2;
}Fushu operator++(Fushu &c2, int)
{Fushu tmp;tmp = c2;c2.a++;c2.b++;return tmp;
}void main()
{Fushu c1(1, 2), c2(3, 4);//通过友元函数实现前++操作++c2;  c2.print();//通过类的成员函数实现前--操作--c2;   c2.print();//通过友元函数实现后++操作c2++;c2.print();//通过类的成员函数实现后--操作c2--;c2.print();system("pause");
}

3.3操作符重载的正规写法

通过友元函数可以获取友元类的私有属性,相当于获取了程序的一个后门。
#include <iostream>
using namespace std;class Fushu
{
private:int a;int b;friend ostream& operator<<(ostream &cout, Fushu &c);
public:Fushu(int a=0, int b=0){this->a = a;this->b = b;}void print(){cout << a << "+" << b << "i" << endl;}
public://通过类的成员函数实现前++操作Fushu &operator++(){this->a++;this->b++;return *this;}//通过类的成员函数实现前--操作Fushu& operator--(){this->a--;this->b--;return *this;}//通过类的成员函数实现后--操作Fushu operator--(int)//用缺省参数占位,跟后--区分{Fushu tmp;tmp = *this;this->a--;this->b--;return tmp;}//通过类的成员函数实现后++操作Fushu operator++(int)//用缺省参数占位,跟后--区分{Fushu tmp;tmp = *this;this->a++;this->b++;return tmp;}
};ostream& operator<<(ostream &co, Fushu &c)
{cout << "我是复数:" << endl;cout << c.a << "+" << c.b << "i" << endl;return co;
}void main()
{Fushu c1(1, 2), c2(3, 4);++c2;   c2.print();--c2;    c2.print();c2++;c2.print();c2--;c2.print();cout << 1 << endl;cout << "hello" << endl;//函数返回值当左值的时候,需要返回一个对象的引用, 实现链式编程cout << c2 << "连续" << endl;//没有方法去在cout类里面添加函数operator<<,只能通过全局函数实现。//cout.operator<<( c1);//void operator<<(ostream &out, Complex &c1)system("pause");
}

3.4操作符重载在项目中的应用:

基本的数组框架
Array.h
//Array.h
#ifndef _ARRAY_H_
#define _ARRAY_H_class Array
{
private:int mLength;//数组的长度int* mSpace;//内存空间public:Array(int length);Array(const Array& obj);//copy构造函数int length();//取得数组长度void setData(int index, int value);int getData(int index);~Array();
};#endif

Array.cpp

//Array.cpp
#include "Array.h"Array::Array(int length)
{if (length < 0){length = 0;}mLength = length;mSpace = new int[mLength];
}
Array::Array(const Array& obj)
{mLength = obj.mLength;mSpace = new int[mLength];for (int i = 0; i<mLength; i++){mSpace[i] = obj.mSpace[i];}
}
int Array::length()
{return mLength;
}
void Array::setData(int index, int value)
{mSpace[index] = value;
}
int Array::getData(int index)
{return mSpace[index];
}
Array::~Array()
{mLength = -1;delete[] mSpace;
}

//ArrayTest.cpp

//ArrayTest.cpp
#include "Array.h"
#include <iostream>
using namespace std;int main()
{Array a1(10);for (int i = 0; i<a1.length(); i++){a1.setData(i, i);  //a[i] = 1;}for (int i = 0; i<a1.length(); i++){printf("array %d: %d\n", i, a1.getData(i));// printf("array %d: %d\n", i, a1[i]));}Array a2 = a1;for (int i = 0; i<a2.length(); i++){printf("array %d: %d\n", i, a2.getData(i));}system("pause");return 0;
}

重载[]  =  ==  !=操作符后的代码:

//Array.h
#ifndef _ARRAY_H_
#define _ARRAY_H_
#include <string.h>
class Array
{
private:int mLength;//数组的长度int* mSpace;//内存空间public:Array(int length);Array(const Array& obj);//copy构造函数int length();//取得数组长度void setData(int index, int value);int getData(int index);~Array();
public:int & operator[](int i);void operator=(Array &a2);bool operator==(Array &a1);bool operator!=(Array &a1);
};#endif
//Array.cpp
#include "Array.h"Array::Array(int length)
{if (length < 0){length = 0;}mLength = length;mSpace = new int[mLength];
}
Array::Array(const Array& obj)
{mLength = obj.mLength;mSpace = new int[mLength];for (int i = 0; i<mLength; i++){mSpace[i] = obj.mSpace[i];}
}
int Array::length()
{return mLength;
}
void Array::setData(int index, int value)
{mSpace[index] = value;
}
int Array::getData(int index)
{return mSpace[index];
}
Array::~Array()
{mLength = -1;delete[] mSpace;
}int& Array::operator[](int i)
{return this->mSpace[i];
}void Array::operator = (Array &a2)
{if (this->mSpace != NULL){delete[] mSpace;}    mLength = a2.mLength;mSpace = new int[mLength];memcpy(mSpace, a2.mSpace, mLength);
}bool Array::operator==(Array &a1)
{//先比较长度if (mLength != a1.mLength){return false;}//比较内容for (int i = 0; i < a1.mLength; i++){if (a1[i] != mSpace[i]){return false;}}return true;
}
//利用相等判断不等
bool Array::operator!=(Array &a1)
{return !(a1 == *this);
}
//ArrayTest.cpp
#include "Array.h"
#include <iostream>
using namespace std;int main()
{Array a1(10);for (int i = 0; i<a1.length(); i++){//a1.setData(i, i);  a1[i] = i;}for (int i = 0; i<a1.length(); i++){//printf("array %d: %d\n", i, a1.getData(i));printf("array %d: %d\n", i, a1[i]);}Array a2 = a1;for (int i = 0; i<a2.length(); i++){//printf("array %d: %d\n", i, a2.getData(i));printf("array %d: %d\n", i, a1[i]);}Array a3(10);a3 = a2; //执行=操作if (a2 == a1){printf("相等");}else{printf("不相等");}system("pause");return 0;
}

【C/C++学院】(8)全局函数和类成员函数转化/友元/操作符重载相关推荐

  1. 10.2 运算符重载函数作为类成员函数和友元函数

    Complex operator+(Complex &c2) { Complex c; c.real=real+c2.real; c.imag=imag+c2.imag; return c; ...

  2. C++运算符重载函数作为类成员函数和友元函数

    C++运算符重载函数作为类成员函数 1.1成员函数的重载运算符左侧是一个类对象,而且与运算符函数类型相同. 因为必须通过类的对象去调用该类的成员函数,而且只有运算符重载函数和返回值类型相同,运算结果才 ...

  3. c++ 线程函数(类成员函数作为线程函数使用)

    C++类成员函数使用时,都会隐式传递一个this指针给该函数,this指针指向该类的对象.函数体可以通过显示调用该指针或直接访问类内成员. 回调函数是通过指针调用的函数,最常使用的回调函数就是在创建线 ...

  4. C++ 函数指针 类成员函数指针

    一.函数指针 函数存放在内存的代码区域内,它们同样有地址.如果我们有一个int test(int a)的函数,那么,它的地址就是函数的名字,这一点如同数组一样,数组的名字就是数组的起始地址. 1.函数 ...

  5. C++中 线程函数为静态函数 及 类成员函数作为回调函数(转载)

    C++中 线程函数为静态函数 及 类成员函数作为回调函数 线程函数为静态函数: 线程控制函数和是不是静态函数没关系,静态函数是在构造中分配的地址空间,只有在析构时才释放也就是全局的东西,不管线程是否运 ...

  6. linux线程创建 类函数吗,linux多线程创建时使用类成员函数作为参数

    实际上所有线程都是用来处理C函数的,而不是C++类成员函数.标准库中提供一个API函数,这个函数以回调函数指针作为线程的执行代码并在单独的线程中调用回调函数.问题是在这样的线程库中不能创建执行对象成员 ...

  7. 关于使用类成员函数作为回调的方法

    为什么类成员函数不能直接做为回调函数? 因为windows中,回调函数都是显式使用CALLBACk修饰符修饰,也就是_stdcall参数传递方式._stdcall修饰的函数,参数从右至左依次压入堆栈, ...

  8. C++深度解析 类中的函数重载 -- 全局函数,普通成员函数,静态成员函数(28)

    C++深度解析 类中的函数重载 -- 全局函数,普通成员函数,静态成员函数(28) 函数重载的回顾 函数重载的本质为相互独立的不同函数 C++中通过函数名和函数参数确定函数调用 无法直接通过函数名得到 ...

  9. C++类的成员函数(在类外定义成员函数、inline成员函数)

    类的成员函数(简称类函数)是函数的一种,它的用法和作用和前面介绍过的函数基本上是一样的,它也有返回值和函数类型,它与一般函数的区别只是:它是属于一个类的成员,出现在类体中.它可以被指定为private ...

最新文章

  1. matlab i型级联filter,Matlab中filter,conv,impz用法(最新整理)
  2. lambda表达式的使用 || Lambda Express 口诀: 拷贝小括号,写死右箭头,落地大括号||default || @FunctionalInterface||静态方法实现
  3. TCL with SNPS collection_limitget_lib_pins
  4. 【MM系列】SAP 簇表 A017 物料信息记录 (指定工厂) 包含的透明表
  5. [转载] Java中的命名参数
  6. 利用jemalloc分析内存泄漏以及LD_PRELOAD
  7. datagrid sortname如何定义多列_如何实现一个小说分页的功能
  8. 2021-08-15 Servlet Properties 读取资源
  9. myeclipse10破解补丁激活方法
  10. 3.1.4_cardView原理解析
  11. [Bada开发]基于bada1.0的5种控件介绍[待续]
  12. 前端工作中碰到的一些小问题总结
  13. 【PostgreSQL逻辑复制数据同步到kafka】
  14. 快速增加闲鱼浏览量,就靠这些方法
  15. 总结:大学实验室的教授喜欢什么样的本科实习学生
  16. LeetCode刷题分类
  17. c语言实现单链表逆序算法,C语言解字符串逆序和单向链表逆序问题的代码示例...
  18. 华为交换机 access,trunk,hybrid理解,需一点基础,应该是最完整的
  19. java使用md5以及jar包下载
  20. 华为OD机试 - 箱子之字形摆放

热门文章

  1. ME02 认知之2017罗胖跨年演讲
  2. Mysql事务-MVCC
  3. html5秘籍当当,酱料制作秘籍
  4. 推荐给大家一款免费的跨境电商免费选品软件
  5. Unity如何批量修改材质的属性
  6. MPB:中农戴兆来组-​猪肠道微生物的体外培养与功能研究
  7. 如何清理占用计算机内存,电脑内存占用太高怎么办?教你一招轻松解决~-怎么清理电脑内存...
  8. linux系统下,wps缺少windows字体的问题。
  9. opc客户端读取数据品质是bad_听说看了这篇文章就彻底搞懂了什么是OPC(上)
  10. C#模拟百度登录并到指定网站评论回帖(三)