C++深度解析教程筆記9
- 第25課 - 類的靜態成員變量
- 實驗-數對象個數(失敗)
- 實驗-靜態變量
- 小結
- 第26課 - 類的靜態成員函數
- 實驗-修改對象的靜態變量數值
- 實驗-利用靜態成員函數
- 實驗-靜態變量+靜態函數實現統計對象個數
- 小結
- 第27課 - 二階構造模式
- 實驗-初始化是否成功
- 實驗-二階構造例子
- 實驗-二階構造數組類
- 小結
- 第28課 - 友元的尷尬能力
- 實驗-友元
- 實驗-友元不具有傳遞性
- 小結
- 第29課 - 類中的函數重載
- 實驗
- 實驗
- 實驗
- 小結
- 第30課 - 操作符重載的概念
- 實驗-友元實現復數相加
- 實驗-操作符重載
- 實驗
- 小結
- 第31課 - 完善的復數類
- 實驗
- 小結
本文學習自狄泰軟件學院 唐佐林老師的 C++深度解析教程,圖片全部來源于課程PPT,僅用于個人學習記錄
第25課 - 類的靜態成員變量
成員變量不能在對象間共享,是專屬的,可通過對象名訪問public成員變量
需求
實驗-數對象個數(失敗)
#include <stdio.h>class Test
{
private:int mCount;
public:Test() : mCount(0){mCount++;}~Test(){--mCount;}int getCount(){return mCount;}
};Test gTest;int main()
{Test t1;Test t2;printf("count = %d\n", gTest.getCount());printf("count = %d\n", t1.getCount());printf("count = %d\n", t2.getCount());return 0;
}
/*
期望輸出1 2 3,實際輸出:
count = 1
count = 1
count = 1
*/
實驗-靜態變量
#include <stdio.h>class Test
{
private:static int cCount;//靜態
public:Test(){cCount++;}~Test(){--cCount;}int getCount(){return cCount;}
};int Test::cCount = 0;Test gTest;int main()
{Test t1;Test t2;printf("count = %d\n", gTest.getCount());printf("count = %d\n", t1.getCount());printf("count = %d\n", t2.getCount());Test* pt = new Test();printf("count = %d\n", pt->getCount());delete pt;printf("count = %d\n", gTest.getCount());return 0;
}
/*
count = 3
count = 3
count = 3
count = 4
count = 3*/
小結
類中可以通過static關鍵定義靜態成員變量
靜態成員變量
第26課 - 類的靜態成員函數
問題:不能隨時獲取當前對象的數據,沒有安全性,使用了全局變量
實驗-修改對象的靜態變量數值
#include <stdio.h>class Test
{
public:static int cCount;
public:Test(){cCount++;}~Test(){--cCount;}int getCount(){return cCount;}
};int Test::cCount = 0;int main()
{printf("count = %d\n", Test::cCount);//count = 0Test::cCount = 1000;//可以修改數值,安全性問題printf("count = %d\n", Test::cCount);//count = 1000return 0;
}
實驗-利用靜態成員函數
#include <stdio.h>class Demo
{
private:int i;
public:int getI();static void StaticFunc(const char* s);//靜態函數static void StaticSetI(Demo& d, int v);//靜態函數
};int Demo::getI()
{return i;
}void Demo::StaticFunc(const char* s)
{printf("StaticFunc: %s\n", s);
}void Demo::StaticSetI(Demo& d, int v)
{d.i = v;
}int main()
{Demo::StaticFunc("main Begin...");//不需要對象,通過類直接調用Demo d;Demo::StaticSetI(d, 10);printf("d.i = %d\n", d.getI());Demo::StaticFunc("main End...");return 0;
}
/*
StaticFunc: main Begin...
d.i = 10
StaticFunc: main End...*/
實驗-靜態變量+靜態函數實現統計對象個數
#include <stdio.h>class Test
{
private:static int cCount;
public:Test(){cCount++;}~Test(){--cCount;}static int GetCount(){return cCount;}
};int Test::cCount = 0;int main()
{printf("count = %d\n", Test::GetCount());Test t1;Test t2;printf("count = %d\n", t1.GetCount());printf("count = %d\n", t2.GetCount());Test* pt = new Test();printf("count = %d\n", pt->GetCount());delete pt;printf("count = %d\n", Test::GetCount());return 0;
}
/*count = 0
count = 2
count = 2
count = 3
count = 2
*/
小結
第27課 - 二階構造模式
實驗-初始化是否成功
#include <stdio.h>class Test
{int mi;int mj;bool mStatus;//記錄初始化是否成功
public:Test(int i, int j) : mStatus(false){mi = i;return;//endmj = j;mStatus = true;}int getI(){return mi;}int getJ(){return mj;}int status()//獲取狀態{return mStatus;}
};int main()
{ Test t1(1, 2);// printf("t1.mi = %d\n", t1.getI());//printf("t1.mj = %d\n", t1.getJ());//不成功if( t1.status() ){printf("t1.mi = %d\n", t1.getI());printf("t1.mj = %d\n", t1.getJ());}return 0;
}
IntArray::IntArray(int len)
{//m_pointer = 0;//new int[len];case1m_pointer = new int[len];//case2if(m_pointer){for(int i=0; i<len; i++){m_pointer[i] = 0;}}m_length = len;
}int main()
{IntArray a(5);a.set(2, 3); printf("%d\n", a.length()); a.free(); return 0;
}
cyz@cyz-virtual-machine:~/桌面/testcpp$ g++ main.cpp IntArray.cpp
cyz@cyz-virtual-machine:~/桌面/testcpp$ ./a.out
段錯誤 (核心已轉儲)
cyz@cyz-virtual-machine:~/桌面/testcpp$ g++ main.cpp IntArray.cpp
cyz@cyz-virtual-machine:~/桌面/testcpp$ ./a.out
5
實驗-二階構造例子
#include <stdio.h>class TwoPhaseCons
{
private:TwoPhaseCons() // 第一階段構造函數{ //與系統資源無關的初始化 }bool construct() // 第二階段構造函數{ //與系統資源相關關的初始化return true; }
public:static TwoPhaseCons* NewInstance(); // 對象創建函數
};TwoPhaseCons* TwoPhaseCons::NewInstance()
{TwoPhaseCons* ret = new TwoPhaseCons();// 若第二階段構造失敗,返回 NULL if( !(ret && ret->construct()) ) {delete ret;//刪除半成品ret = NULL;}return ret;
}int main()
{TwoPhaseCons* obj = TwoPhaseCons::NewInstance();printf("obj = %p\n", obj);//obj = 0000000002521CB0delete obj;return 0;
}
實驗-二階構造數組類
//h文件 修改
class IntArray
{
private:int m_length;int* m_pointer;IntArray(int len) ;// 第一階段構造函數bool construct() ;// 第二階段構造函數IntArray(const IntArray& obj);public:
static IntArray* NewInstance(int length); // 對象創建函數 靜態成員函數//IntArray(int len);//構造函數改為私有 作為第一階段構造函數int length();bool get(int index, int& value);bool set(int index ,int value);~IntArray();
};
//IntArray.cpp
IntArray::IntArray(int len)//第一階段構造函數
{m_length = len;
}
bool IntArray::construct() // 第二階段構造函數{ bool ret=true;m_pointer = new int[m_length];//與系統資源相關關的初始化if(m_pointer){for(int i=0; i<m_length; i++){m_pointer[i] = 0;}}else{ret=false;}return ret; }
IntArray* IntArray::NewInstance(int length)// 對象創建函數
{IntArray* ret = new IntArray(length);//new 第一階段構造函數 // 若第二階段構造失敗,返回 NULL if( !(ret && ret->construct()) ) {delete ret;//刪除半成品ret = 0;}return ret;
}
IntArray::~IntArray()
{delete[]m_pointer;//printf("~IntArray()\n");
}//main.cppIntArray* a = IntArray::NewInstance(5); printf("a.length = %d\n", a->length());a->set(0, 1);for(int i=0; i<a->length(); i++){int v = 0;a->get(i, v);printf("a[%d] = %d\n", i, v);}delete a;
小結
第28課 - 友元的尷尬能力
實驗-友元
#include <stdio.h>
#include <math.h>class Point
{double x;double y;
public:Point(double x, double y){this->x = x;this->y = y;}double getX(){return x;}double getY(){return y;}friend double func(Point& p1, Point& p2);//友元 實現訪問類
//friend double func(Point& p1, Point& p2);//注釋后 error: 'double Point::y' is private within this context
};double func(Point& p1, Point& p2)
{double ret = 0;ret = (p2.y - p1.y) * (p2.y - p1.y) +(p2.x - p1.x) * (p2.x - p1.x);ret = sqrt(ret);return ret;
}int main()
{Point p1(1, 2);Point p2(10, 20);printf("p1(%f, %f)\n", p1.getX(), p1.getY());//p1(1.000000, 2.000000)printf("p2(%f, %f)\n", p2.getX(), p2.getY());//p2(10.000000, 20.000000)printf("|(p1, p2)| = %f\n", func(p1, p2));//|(p1, p2)| = 20.124612return 0;
}
實驗-友元不具有傳遞性
#include <stdio.h>class ClassC
{const char* n;
public:ClassC(const char* n){this->n = n;}friend class ClassB;//B可以訪問C的成員
};class ClassB
{const char* n;
public:ClassB(const char* n){this->n = n;}void getClassCName(ClassC& c){printf("c.n = %s\n", c.n);}friend class ClassA;//A可以訪問B的成員
};
//無傳遞性,A不可以訪問C的成員
class ClassA
{const char* n;
public:ClassA(const char* n){this->n = n;}void getClassBName(ClassB& b){printf("b.n = %s\n", b.n);}/*void getClassCName(ClassC& c)//error: 'const char* ClassC::n' is private within this context{printf("c.n = %s\n", c.n);}*/};int main()
{ClassA A("A");ClassB B("B");ClassC C("C");A.getClassBName(B);//b.n = BB.getClassCName(C);//c.n = Creturn 0;
}
小結
第29課 - 類中的函數重載
實驗
#include <stdio.h>class Test
{int i;
public:Test(){printf("Test::Test()\n");this->i = 0;}Test(int i){printf("Test::Test(int i)\n");this->i = i;}Test(const Test& obj){printf("Test(const Test& obj)\n");this->i = obj.i;}static void func(){printf("void Test::func()\n");}void func(int i){printf("void Test::func(int i), i = %d\n", i);}int getI(){return i;}
};void func()//全局函數1
{printf("void func()\n");
}void func(int i)//全局函數2
{printf("void func(int i), i = %d\n", i);
}int main()
{func();func(1);Test t; // Test::Test()Test t1(1); // Test::Test(int i)Test t2(t1); // Test(const Test& obj)func(); // void func()Test::func(); // void Test::func()func(2); // void func(int i), i = 2;t1.func(2); // void Test::func(int i), i = 2t1.func(); // void Test::func()return 0;
}
/*
void func()
void func(int i), i = 1
Test::Test()
Test::Test(int i)
Test(const Test& obj)
void func()
void Test::func()
void func(int i), i = 2
void Test::func(int i), i = 2
void Test::func()*/
實驗
#include <stdio.h>
#include <string.h>char* strcpy(char* buf, const char* str, unsigned int n)
{return strncpy(buf, str, n);
}int main()
{const char* s = "D.T.Software";char buf[8] = {0};//strcpy(buf, s);//報錯,放不下字符串strcpy(buf, s, sizeof(buf)-1);//利用重載擴展原有函數的功能printf("%s\n", buf);//D.T.Sofreturn 0;
}
實驗
在這里插入代碼片
小結
第30課 - 操作符重載的概念
實驗-友元實現復數相加
#include <stdio.h>class Complex
{int a;int b;
public:Complex(int a = 0, int b = 0){this->a = a;this->b = b;}int getA(){return a;}int getB(){return b;}friend Complex Add(const Complex& p1, const Complex& p2);
};Complex Add(const Complex& p1, const Complex& p2)
{Complex ret;ret.a = p1.a + p2.a;ret.b = p1.b + p2.b;return ret;
}int main()
{Complex c1(1, 2);Complex c2(3, 4);Complex c3 = Add(c1, c2); // c1 + c2printf("c3.a = %d, c3.b = %d\n", c3.getA(), c3.getB());//c3.a = 4, c3.b = 6return 0;
}
實驗-操作符重載
#include <stdio.h>class Complex
{int a;int b;
public:Complex(int a = 0, int b = 0){this->a = a;this->b = b;}int getA(){return a;}int getB(){return b;}friend Complex operator + (const Complex& p1, const Complex& p2);
};Complex operator + (const Complex& p1, const Complex& p2)
{Complex ret;ret.a = p1.a + p2.a;ret.b = p1.b + p2.b;return ret;
}int main()
{Complex c1(1, 2);Complex c2(3, 4);Complex c3 = operator+(c1, c2);//Complex c3 = c1 + c2; printf("c3.a = %d, c3.b = %d\n", c3.getA(), c3.getB());//c3.a = 4, c3.b = 6return 0;
}
實驗
#include <stdio.h>class Complex
{int a;int b;
public:Complex(int a = 0, int b = 0){this->a = a;this->b = b;}int getA(){return a;}int getB(){return b;}Complex operator + (const Complex& p){Complex ret;printf("Complex operator + (const Complex& p)\n");ret.a = this->a + p.a;ret.b = this->b + p.b;return ret;}friend Complex operator + (const Complex& p1, const Complex& p2);
};Complex operator + (const Complex& p1, const Complex& p2)
{Complex ret;printf("Complex operator + (const Complex& p1, const Complex& p2)\n");ret.a = p1.a + p2.a;ret.b = p1.b + p2.b;return ret;
}int main()
{Complex c1(1, 2);Complex c2(3, 4);Complex c3 = c1 + c2; // c1.operator + (c2)printf("c3.a = %d, c3.b = %d\n", c3.getA(), c3.getB());return 0;
}
/*
Complex operator + (const Complex& p)
c3.a = 4, c3.b = 6
*/
編譯器優先調用類中的函數,其次才是全局函數
小結
第31課 - 完善的復數類
實驗
#ifndef _COMPLEX_H_
#define _COMPLEX_H_class Complex
{
private:double a;double b;
public:Complex(double a=0,double b=0);double getA();double getB();double getmodulus();Complex operator+(const Complex& c);Complex operator-(const Complex& c);Complex operator*(const Complex& c);Complex operator/(const Complex& c);bool operator==(const Complex& c);bool operator!=(const Complex& c);Complex& operator=(const Complex& c);};
#endif // _COMPLEX_H_#include "Complex.h"
#include "math.h"Complex::Complex(double a,double b)
{this->a=a;this->b=b;
}
double Complex::getA()
{return a;
}
double Complex::getB(){return b;
}
double Complex::getmodulus()
{double res=sqrt(a*a+b*b);return res;
}Complex Complex::operator+(const Complex& c)
{double na=a+c.a;double nb=b+c.b;Complex res=Complex(na,nb);return res;
}
Complex Complex::operator-(const Complex& c)
{double na=a-c.a;double nb=b-c.b;Complex res=Complex(na,nb);return res;}
Complex Complex::operator*(const Complex& c)
{double na=a*c.a-b*c.b;double nb=a*c.b+b*c.a;Complex res=Complex(na,nb);return res;}
Complex Complex::operator/(const Complex& c)
{double m=c.a*c.a+c.b*c.b;double na=(a*c.a+b*c.b)/m;double nb=(-a*c.b+b*c.a)/m;Complex res=Complex(na,nb);return res;}bool Complex::operator==(const Complex& c){return a==c.a&&b==c.b;}
bool Complex::operator!=(const Complex& c)
{return !(a==c.a&&b==c.b);}
Complex& Complex::operator=(const Complex& c){if(this!=&c){a=c.a;b=c.b;}return *this;}//main.cpp
#include <stdio.h>
#include "Complex.h"int main()
{Complex a1(1,2);Complex a2(3,4);Complex a3=a1+a2;printf("%f %f\n",a3.getA(),a3.getB());printf("a3.getmodulus()=%f\n",a3.getmodulus());a3=a1-a2;printf("a1-a2 %f %f\n",a3.getA(),a3.getB());a3=a1*a2;printf("a1*a2%f %f\n",a3.getA(),a3.getB());a3=a1/a2;printf("a1/a2%f %f\n",a3.getA(),a3.getB());Complex a4=a1;printf("%f %f\n",a4.getA(),a4.getB());printf("a4==a1 %d a4!=a1 %d\n",a4==a1,a4!=a1);return 0;
}