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;
}