Bootstrap

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



在这里插入图片描述

小结

在这里插入图片描述

;