您好,登錄后才能下訂單哦!
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 <iostream> #include <stdlib.h> 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 <iostream> #include <stdlib.h> using namespace std; class A { public: void fun() { cout << "a="<<this->a<<" b="<<this->b<< " in fun"<<endl; } A(int a=0,int b=0) { this->a = a; this->b = b; cout << "a="<<this->a<<" b="<<this->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= "<<a << " b="<<b <<" free\n"; } public: int a; int b; }; //把成員函數轉成全局函數 A fun(A &a1,A &a2) { A a3; return a3; } void fun1() { cout << "-------- in fun1 ------------------- \n"; A a1(1,2); A a2(3,4); A a3 = a1.add(a2); a3.fun(); } void fun2() { cout << "-------- in fun2 ------------------- \n"; A a1(1,2); A a2(3,4); A a3(5,5); a3 = a1.add(a2); a3.fun(); } int main() { fun1(); fun2(); return 0; } chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out -------- in fun1 ------------------- a=1 b=2 in init a=3 b=4 in init a=4 b=6 in init a=4 b=6 in fun a= 4 b=6 free a= 3 b=4 free a= 1 b=2 free -------- in fun2 ------------------- a=1 b=2 in init a=3 b=4 in init a=5 b=5 in init a=4 b=6 in init a= 4 b=6 free a=4 b=6 in fun a= 4 b=6 free a= 3 b=4 free a= 1 b=2 free
成員函數返回*this
chunli@Linux:~/c++$ cat main.cpp #include <iostream> #include <stdlib.h> using namespace std; class A { public: void fun() { cout << "a="<<this->a<<" b="<<this->b<< " in print"<<endl; } A(int a=0,int b=0) { this->a = a; this->b = b; cout << "a="<<this->a<<" b="<<this->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="<<a << " b="<<b <<" free\n"; } public: int a; int b; }; int main() { A a1(1,2); A a2(3,4); a1.add(a2); a1.fun(); return 0; } chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out a=1 b=2 in init a=3 b=4 in init a=4 b=6 in print a=3 b=4 free a=4 b=6 free chunli@Linux:~/c++$
自定義數組類封裝 具有以下函數
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" #include <iostream> using 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<this->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 <iostream> #include "my_arr.h" #include <stdlib.h> using namespace std; int main() { Arr a1(20); for(int i = 0;i<a1.arr_len();i++) { a1.arr_set(i,i); } for(int i = 0;i<a1.arr_len();i++) { cout << a1.arr_get(i) << " "; } cout << endl; Arr a2 = a1; //等號操作,C++編譯器會調用拷貝構造函數 for(int i = 0;i<a2.arr_len();i++) { cout << a2.arr_get(i) << " "; } cout << endl; return 0; }
編譯運行:
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 <iostream> #include <stdlib.h> 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 <iostream> #include <stdlib.h> 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 <iostream> #include <stdlib.h> 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 <iostream> #include <stdlib.h> using namespace std; class A { public: A(int a,int b) { this->a = a; this->b = b; } int printf() { cout <<a<<" "<<b<<endl; } int a; int b; }; A operator+(A &a,A &b) { cout << "Hello World \n"; A t(a.a+b.a,a.b+b.b); return t; } int main() { A a1(1,1); A a2(2,2); A a3 = a1+a2; a3.printf(); return 0; } chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out Hello World 3 3 chunli@Linux:~/c++$
可以進行運算符重載的符合
不可以進行運算符重載的符合
【二元操作符】成員函數的運算符重載
此時的成員變量還都是public的
chunli@Linux:~/c++$ cat main.cpp #include <iostream> using 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 <<a<<" "<<b<<endl; } int a; int b; }; int main() { A a1(1,1); A a2(2,2); A a3 = a1+a2; a3.printf(); return 0; } chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out 成員函數的 運算符重載 4 4
【二元操作符】全局函數的運算符重載
此時的成員變量都是private的
chunli@Linux:~/c++$ cat main.cpp #include <iostream> using 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 <<a<<" "<<b<<endl; } private: int a; int b; }; A operator+(A &a,A &b) { cout << "Hello World \n"; A t(a.a+b.a,a.b+b.b); return t; } int main() { A a1(1,1); A a2(2,2); A a3 = a1+a2; a3.printf(); return 0; } chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out Hello World 3 3
【二元操作符】成員函數的運算符重載
此時的成員變量都是private的
chunli@Linux:~/c++$ cat main.cpp #include <iostream> using 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 <<a<<" "<<b<<endl; } private: int a; int b; }; int main() { A a1(1,1); A a2(2,2); A a3 = a1+a2; a3.printf(); return 0; } chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out 成員函數的 運算符重載 4 4
【一元運算符】前置++
全局函數 運算符重載
chunli@Linux:~/c++$ cat main.cpp #include <iostream> using namespace std; class A { friend A& operator++(A &a); public: A(int a,int b) { this->a = a; this->b = b; } int printf() { cout <<a<<" "<<b<<endl; } private: int a; int b; }; A& operator++(A &a) { cout << "成員函數的 運算符重載 \n"; a.a++; a.b++; return a; } int main() { A a1(1,1); ++a1; a1.printf(); return 0; } chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out 成員函數的 運算符重載 2 2
【一元運算符】前置++
成員函數 運算符重載
chunli@Linux:~/c++$ cat main.cpp #include <iostream> using 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 <<a<<" "<<b<<endl; } private: int a; int b; }; int main() { A a1(1,1); ++a1; a1.printf(); return 0; } chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out 成員函數的 運算符重載 2 2 chunli@Linux:~/c++$
全局函數 成員函數
前置++ 后置++
前置-- 后置--
【注意】全局函數的聲明 要與友元函數的聲明一致
chunli@Linux:~/c++$ cat main.cpp #include <iostream> using 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 <<a<<" "<<b<<endl; } private: int a; int b; }; A& operator--(A &t) { cout << "前置-- 一元運算符重載 "; t.a--; t.b--; return t; } A operator--(A &from,int) { cout << "后置-- 一元 運算符重載 "; A t(from); from.a--; from.b--; return t; } int main() { A aa(5,6); A a1(aa++); a1.printf(); A ab(5,6); A a2(++ab); a2.printf(); A ac(5,6); A a3(ac--); a3.printf(); A ad(5,6); A a4(--ad); a4.printf(); return 0; } chunli@Linux:~/c++$ g++ -Wall -g main.cpp && ./a.out 后置++ 一元 運算符重載 5 6 前置++ 一元運算符重載 6 7 后置-- 一元 運算符重載 5 6 前置-- 一元運算符重載 4 5 chunli@Linux:~/c++$
有元函數的正真使用場景:
使用cout輸出一個自定義類的成員變量,必須修改ostream類源碼
在拿不到iostream的源代碼的情景下,只能使用友元函數
chunli@Linux:~/c++$ cat main.cpp #include <iostream> using 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 <<a<<" "<<b<<endl; } private: int a; int b; }; void operator<<(ostream &friend_ship,A &from) { friend_ship << "友元函數的真正應用場景\n"; friend_ship << from.a << " " <<from.b<< endl; } int main() { A a(5,6); cout << a; return 0; } chunli@Linux:~/c++$ g++ -Wall -g main.cpp && ./a.out 友元函數的真正應用場景 5 6
鏈式輸出對象的信息 cout << a << a;
chunli@Linux:~/c++$ cat main.cpp #include <iostream> using 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 <<a<<" "<<b<<endl; } private: int a; int b; }; //鏈式輸出 需要返回一個引用 // <<操作符是至左向右結合 ostream & operator<<(ostream &friend_ship,A &from) { friend_ship << "友元函數的真正應用場景\n"; friend_ship << from.a << " " <<from.b<< endl; return friend_ship; } int main() { A a(5,6); cout << a << a; return 0; } chunli@Linux:~/c++$ g++ -Wall -g main.cpp && ./a.out 友元函數的真正應用場景 5 6 友元函數的真正應用場景 5 6
運算符重載提高:1
等號 = 運算符重載: 支持鏈式操作
【難點】 釋放之前的指針,返回一個引用
chunli@Linux:~/c++$ cat main.cpp #include <iostream> #include <stdlib.h> #include <string.h> 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 <<from.p<< " -> 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 #include <iostream> using 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<a1.len;i++) { a1[i] = i * i; } for(int i = 0;i<a1.len;i++) { cout << a1[i] << " "; } cout << "\n"; return 0; } chunli@Linux:~/c++$ g++ -Wall -g main.cpp && ./a.out 0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225
【強化數組類練習!】等號=運算符重載,中括號[]運算符重載
chunli@Linux:~/c++$ cat main.cpp #include <iostream> using 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<from.len;i++) { this->p[i] = from.p[i]; } return *this; } void out() { for(int i = 0;i<this->len;i++) { cout << this->p[i] << "\t"; } cout << "\n"; } void init(int num) { for(int i = 0;i<this->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 #include <iostream> using 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<from.len;i++) { this->p[i] = from.p[i]; } return *this; } bool operator!=(Arr &from) { if(this->len != from.len) { return true; } for(int i = 0;i<from.len;i++) { if(this->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<from.len;i++) { if(this->p[i] != from.p[i]) { return false; } } return true; } void out() { for(int i = 0;i<this->len;i++) { cout << this->p[i] << "\t"; } cout << "\n"; } void init(int num) { for(int i = 0;i<this->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
運算符結合方向:
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。