C++深度解析教程笔记9
本文学习自狄泰软件学院 唐佐林老师的 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 = 0
Test::cCount = 1000;//可以修改数值,安全性问题
printf("count = %d\n", Test::cCount);//count = 1000
return 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;//end
mj = 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];case1
m_pointer = new int[len];//case2
if(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 = 0000000002521CB0
delete 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.cpp
IntArray* 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.124612
return 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 = B
B.getClassCName(C);//c.n = C
return 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 = 2
t1.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.Sof
return 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 + c2
printf("c3.a = %d, c3.b = %d\n", c3.getA(), c3.getB());//c3.a = 4, c3.b = 6
return 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 = 6
return 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;
}