1)
专注于为中小企业提供成都网站建设、网站设计服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业怒江州免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上千企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
请问类中函数 const修饰的谁
把类中的成员函数 转换成全局函数
成员函数返回*this
2)
自定义数组类封装 申明 与实现分开写 具有以下函数
void arr_set(int n,int value);
int arr_get(int n);
int arr_len()
3)
为什么会有友元函数
友元类:
4)
运算符重载
可以进行运算符重载的符
【二元操作符】 + -
全局函数的运算符重载,private成员变量
成员函数的运算符重载,private成员变量
【一元运算符】
成员函数,全局函数
前置++ 后置++
前置-- 后置--
有元函数的正真使用场景:
返回引用类型,链式输出对象的信息
5)
【难点】运算符重载提高
等号=
中括号[],当左值,当右值
相等符号 ==
不等于 !=
6)作业:封装一个字符类,使用 << ,>>,!= ,==,=,
附:运算符结合方向:
1,请问类中函数 const修饰的谁?
chunli@Linux:~/c++$ cat main.cpp #include#include using namespace std; class A { public: //const的三种写法 //const void fun(int a,int b) //void const fun(int a,int b) //void fun(int a,int b) const void fun(int a,int b) const { a = 100; //const 修饰的不是a //this->a = 200; //编译提示:‘A::a’ in read-only object } private: int a; int b; }; int main() { A a1; return 0; }
答案:
const的三种写法修饰的是this指针
const void fun(int a,int b)
void const fun(int a,int b)
void fun(int a,int b) const
this指针所指向的内存空间不能被修改
相当于 void fun(const A *this,int a,int b)
修改this指针本身的值,编译也不通过
把类中的成员函数 转换成全局函数
chunli@Linux:~/c++$ cat main.cpp #include#include using namespace std; class A { public: void fun() { cout << "a="< a<<" b="< b<< " in fun"< a = a; this->b = b; cout << "a="< a<<" b="< b<<" in init \n"; } A add(A &a) { A t(this->a + a.a,this->b + a.b); return t; } A (const A &obj) { cout << "in copy \n"; } ~A() { cout << "a= "< 成员函数返回*this
chunli@Linux:~/c++$ cat main.cpp #include#include using namespace std; class A { public: void fun() { cout << "a="< a<<" b="< b<< " in print"< a = a; this->b = b; cout << "a="< a<<" b="< b<<" in init \n"; } //返回一个引用,相当于返回自身 A& add(A &a) { this->a += a.a, this->b += a.b; return *this; } A (const A &obj) { cout << "in copy \n"; } ~A() { cout << "a="< 自定义数组类封装 具有以下函数
void arr_set(int n,int value);
int arr_get(int n);
int arr_len();
文件1:
chunli@Linux:~/c++$ cat my_arr.h #pragma once class Arr { public: void arr_set(int n,int value); int arr_get(int n); int arr_len(); Arr(int n); Arr(const Arr &boj); ~Arr(); private: int len; int *arr; }; chunli@Linux:~/c++$文件2:
chunli@Linux:~/c++$ cat my_arr.cpp #include "my_arr.h" #includeusing namespace std; void Arr::arr_set(int n,int value) { this->arr[n] = value; } int Arr::arr_get(int n) { return this->arr[n]; } int Arr::arr_len() { return this->len; } Arr::Arr(int n) { if(n<1) { len = 0; arr = NULL; } else { this->len = n; arr = new int [n]; cout << n <<" init ...\n"; } } Arr::Arr(const Arr &obj) { this->len = obj.len; arr = new int [this->len]; for(int i = 0;i len;i++) { this->arr[i] = obj.arr[i] + 1; } cout << this->len<<" copy ...\n"; } Arr::~Arr() { if(arr != NULL) { cout << this->len<<" free ...\n"; delete [] arr; len = 0; } } chunli@Linux:~/c++$ 文件3:
chunli@Linux:~/c++$ cat main.cpp #include#include "my_arr.h" #include using namespace std; int main() { Arr a1(20); for(int i = 0;i 编译运行:
chunli@Linux:~/c++$ g++ -g main.cpp my_arr.cpp && ./a.out 20 init ... 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 copy ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 20 free ... 20 free ... chunli@Linux:~/c++$为什么会有友元函数?
在实现类之间数据共享时,减少系统开销,提高效率。
如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数。
具体来说:为了使其他类的成员函数直接访问该类的私有变量。
即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数。
实际上具体大概有下面两种情况需要使用友元函数:
(1)运算符重载的某些场合需要使用友元。
(2)两个类要共享数据的时候。
chunli@Linux:~/c++$ cat main.cpp #include#include using namespace std; class A { public: A(int a,int b) { this->a = a; this->b = b; } private: int a; int b; }; void fun(A *p) { //不能在类的外部访问私有属性 int n =p->a; } int main() { A a1(1,2); fun(&a1); return 0; } 编译就报错: chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out main.cpp: In function ‘void fun(A*)’: main.cpp:13:6: error: ‘int A::a’ is private int a; ^ 把这个函数添加为友元函数就OK了
友元函数 与 位置没有关系
chunli@Linux:~/c++$ cat main.cpp #include#include using namespace std; class A { friend void fun(A *p); public: A(int a,int b) { this->a = a; this->b = b; } int get_a() { return this->a; } private: int a; int b; }; void fun(A *p) { //不能在类的外部访问私有属性 p->a = 10; int n =p->a; cout << n << endl; } int main() { A a1(1,2); fun(&a1); cout << a1.get_a() << endl; return 0; } chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out 10 10 友元类:
chunli@Linux:~/c++$ cat main.cpp #include#include using namespace std; class A { friend class B; private: int a; }; class B { friend void fun(A *p); public: B(int a) { a1.a = a; //可以直接修改友元类的属性 } int get_a() { return this->a1.a;////可以直接修改友元类的属性 } private: int a; A a1; }; int main() { B b1(11); cout << b1.get_a() << "\n"; return 0; } chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out 11 chunli@Linux:~/c++$ 运算符重载,初步
让两个类直接相加减
运算符重载本质是一个函数
约定operator关键字
C++编译器会自动去找运算符
chunli@Linux:~/c++$ cat main.cpp #include#include using namespace std; class A { public: A(int a,int b) { this->a = a; this->b = b; } int printf() { cout < 可以进行运算符重载的符合
不可以进行运算符重载的符合
【二元操作符】成员函数的运算符重载
此时的成员变量还都是public的
chunli@Linux:~/c++$ cat main.cpp #includeusing namespace std; class A { public: A operator+(A obj) { cout << "成员函数的 运算符重载 \n"; A t(this->a + obj.a +1,this->b + obj.b +1 ); return t; } A(int a,int b) { this->a = a; this->b = b; } int printf() { cout < 【二元操作符】全局函数的运算符重载
此时的成员变量都是private的
chunli@Linux:~/c++$ cat main.cpp #includeusing namespace std; class A { friend A operator+(A &a,A &b); public: A(int a,int b) { this->a = a; this->b = b; } int printf() { cout < 【二元操作符】成员函数的运算符重载
此时的成员变量都是private的
chunli@Linux:~/c++$ cat main.cpp #includeusing namespace std; class A { public: A operator+(A obj) { cout << "成员函数的 运算符重载 \n"; A t(this->a + obj.a +1,this->b + obj.b +1 ); return t; } A(int a,int b) { this->a = a; this->b = b; } int printf() { cout < 【一元运算符】前置++
全局函数 运算符重载
chunli@Linux:~/c++$ cat main.cpp #includeusing namespace std; class A { friend A& operator++(A &a); public: A(int a,int b) { this->a = a; this->b = b; } int printf() { cout < 【一元运算符】前置++
成员函数 运算符重载
chunli@Linux:~/c++$ cat main.cpp #includeusing namespace std; class A { public: A& operator++() { cout << "成员函数的 运算符重载 \n"; this->a++; this->b++; return *this; //A& 需要返回一个实体,而不是指针 } A(int a,int b) { this->a = a; this->b = b; } int printf() { cout < 全局函数 成员函数
前置++ 后置++
前置-- 后置--
【注意】全局函数的声明 要与友元函数的声明一致
chunli@Linux:~/c++$ cat main.cpp #includeusing namespace std; class A { friend A& operator--(A &a); friend A operator--(A &a,int); public: A& operator++() { cout << "前置++ 一元运算符重载 "; this->a++; this->b++; return *this; //A& 需要返回一个实体,而不是指针 } A operator++(int) { cout << "后置++ 一元 运算符重载 "; A t = *this; this->a++; this->b++; return t; } A(int a,int b) { this->a = a; this->b = b; } void printf() { cout < 有元函数的正真使用场景:
使用cout输出一个自定义类的成员变量,必须修改ostream类源码
在拿不到iostream的源代码的情景下,只能使用友元函数
chunli@Linux:~/c++$ cat main.cpp #includeusing namespace std; class A { friend void operator<<(ostream &friend_ship,A &from); public: A(int a,int b) { this->a = a; this->b = b; } void printf() { cout < 链式输出对象的信息 cout << a << a;
chunli@Linux:~/c++$ cat main.cpp #includeusing namespace std; class A { friend ostream & operator<<(ostream &friend_ship,A &from); public: A(int a,int b) { this->a = a; this->b = b; } void printf() { cout < 运算符重载提高:1
等号 = 运算符重载: 支持链式操作
【难点】 释放之前的指针,返回一个引用
chunli@Linux:~/c++$ cat main.cpp #include#include #include using namespace std; class Str { public: Str(const char *p) { this->len = strlen(p); this->p = (char*)malloc(this->len + 1); strcpy(this->p,p); this->p[len] = '\0'; cout << this->p << " init\n"; } Str(const Str &from) { this->len = strlen(from.p); this->p =(char*)malloc(this->len + 1); strcpy(this->p,from.p); this->p[this->len] = '\0'; cout << "in copy \n"; } ~Str() { if(this->p != NULL) { cout << this->p << " free\n"; free(this->p); this->p = NULL; this->len = 0; } } Str& operator=(Str &from) { if(this->p != NULL) { free(this->p); //先把自己之前的指针释放掉 } cout < in = operator\n"; this->len = strlen(from.p); this->p = (char*)malloc(this->len + 1); strcpy(this->p,from.p); this->p[len] = '\0'; return *this; } private: char *p; int len; }; int main() { Str s1("Hello"); Str s2("Linux"); Str s3("Google"); s1 = s2 = s3; //对象的赋值操作s1 = s2 ,不会调用赋值构造函数 return 0; } chunli@Linux:~/c++$ g++ -Wall -g main.cpp && ./a.out Hello init Linux init Google init Google -> in = operator Google -> in = operator Google free Google free Google free 中括号[]运算符重载,数组类的
【难点】:函数当右值,函数当左值
chunli@Linux:~/c++$ cat main.cpp #includeusing namespace std; class Arr { public: Arr(int n) { this->len = n; p = new int[n]; } ~Arr() { delete [] p; } int & operator[](int i) { return p[i]; } int len; int *p; }; int main() { Arr a1(16); for(int i = 0;i 【强化数组类练习!】等号=运算符重载,中括号[]运算符重载
chunli@Linux:~/c++$ cat main.cpp #includeusing namespace std; class Arr { public: Arr(int n) { this->len = n; p = new int[n]; } ~Arr() { if(p != NULL) { delete [] p; p = NULL; } } int & operator[](int i) { return p[i]; } Arr & operator=(Arr &from) { if(this->p != NULL) { delete [] p; } this->len = from.len; this->p = new int[this->len]; for(int i=0;i p[i] = from.p[i]; } return *this; } void out() { for(int i = 0;i len;i++) { cout << this->p[i] << "\t"; } cout << "\n"; } void init(int num) { for(int i = 0;i len;i++) { this->p[i] = i + num; } } int len; int *p; }; int main() { Arr a1(16); a1.init(1); a1.out(); Arr a2(10); a2.init(2); a2.out(); a1 = a2; a1.out(); return 0; } chunli@Linux:~/c++$ g++ -Wall -g main.cpp && ./a.out 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2 3 4 5 6 7 8 9 10 11 2 3 4 5 6 7 8 9 10 11 数组的 相等== 运算操作符重载,不等于!= 操作符重载
chunli@Linux:~/c++$ cat main.cpp #includeusing namespace std; class Arr { public: Arr(int n) { this->len = n; p = new int[n]; } ~Arr() { if(p != NULL) { delete [] p; p = NULL; } } int & operator[](int i) { return p[i]; } Arr & operator=(Arr &from) { if(this->p != NULL) { delete [] p; } this->len = from.len; this->p = new int[this->len]; for(int i=0;i p[i] = from.p[i]; } return *this; } bool operator!=(Arr &from) { if(this->len != from.len) { return true; } for(int i = 0;i p[i] != from.p[i]) { return true; } } return false; } bool operator==(Arr &from) { if(this->len != from.len) { return false; } for(int i = 0;i p[i] != from.p[i]) { return false; } } return true; } void out() { for(int i = 0;i len;i++) { cout << this->p[i] << "\t"; } cout << "\n"; } void init(int num) { for(int i = 0;i len;i++) { this->p[i] = i + num; } } int len; int *p; }; int main() { Arr a1(16); a1.init(1); a1.out(); Arr a2(10); a2.init(2); a2.out(); a1 = a2; a1.out(); Arr a3(10); a3.init(1); Arr a4(10); a4.init(1); if(a3 == a4) { cout << "a3 == a4 \n"; } else { cout << "a3 != a4 \n"; } a4.init(2); //修改a4数组的值 if(a3 != a4) { cout << "a3 != a4 \n"; } else { cout << "a3 == a4 \n"; } return 0; } chunli@Linux:~/c++$ g++ -Wall -g main.cpp && ./a.out 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2 3 4 5 6 7 8 9 10 11 2 3 4 5 6 7 8 9 10 11 a3 == a4 a3 != a4 运算符结合方向:
当前名称:C++基础4类const函数转全局函数返回*this数组类。友元函数类操作符重载
网址分享:http://cdweb.net/article/jpheip.html