C++基础 (4) 第四天 this指针 全局函数和成员函数 友元 操作符重载

1static强化练习-仓库进货和出货

 

 

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

 

using namespace std;

 

 

class Goods

{

public:

    // 无参数的构造函数

    Goods()

    {

        next = NULL;

        weight = 0;

        cout << "创建了一个货物重量是" << 0 << "的物品" << endl;

    }

 

    // 有参数的构造函数

    Goods(int w)

    {

        weight = w;

        next = NULL;

   

        // 每创建一个货物 总重量应该加

        cout << "创建了一个货物重量是" << w << "的物品" << endl;

        taotal_weight += w;

    }

 

    // 提供一个静态的成员函数来访问静态成员

    static int getTotal()

    {

        return taotal_weight;

    }

 

    ~Goods()

    {

        cout << "删除了一箱重量是" << weight << "货物" << endl;

        taotal_weight -= weight;

    }

 

    // 给货物类变成一个链表的节点

    Goods * next;

 

private:

    int weight; // 货物的重量

    static int taotal_weight; // 所有货物的总重量

};

 

 

// 一开始所有货物总重量是0

int Goods::taotal_weight = 0;

 

// 进货的方法

void buy(Goods* &head,int w)

{

    // 创建一个新的货物

    Goods *new_goods = new Goods(w); // 通过new在堆上开辟空间,调用了Goods类的有参构造函数

 

    if (head == NULL) {

        // 如果head是空

        head = new_goods; //无头链表

    }

    else

    {

        // 如果head不为空,从head表头添加

        new_goods->next = head;

        head = new_goods;

    }

}

 

 

// 出货的方法

void sale(Goods * &head)

{

    if (head == NULL) {

        cout << "仓库已经没有货物了" << endl;

        return;

    }

   

    Goods *temp = head;

    head = head->next;

    delete temp;

    

    cout << "saled " << endl;

}

 

 

int main(void)

{

    int choice = 0;

 

    Goods *head = NULL; // 所有货物的表头

 

    do {

        cout << "1 进货" << endl;

        cout << "2 出货" << endl;

        cout << "0 退出" << endl;

        cin >> choice;

 

        switch (choice)

        {

        case 1:

            // 进货

            cout << "请输入要创建的货物的重量" << endl;

            int w;

            cin >> w;

            buy(head, w);

            break;

        case 2:

            // 出货

            sale(head);

            break;

        case 0:

            // 退出

            return 0;

            break;

        default:

            break;

        }

 

        cout << "此时仓库中有" <<  Goods::getTotal() <<"重量的货物" << endl;

    } while (1);

 

 

    return 0;

}

 

1 昨日回顾

 

3 this指针

 

 

 

 

4全局函数和成员函数

 

多次调用的实现

 

 

 

5 强化练习2-封装一个自定义的数组类

 

 

 

 

 

 

6 友元函数

 

7 友元类和友元的规则

 

 

 

友元是单向的。

 

8中午回顾

9操作符重载的概念

 

 

 

 

 

10 操作符重载的规则

 

 

.*符号:

  ↑ 这两个参数都是普通类型 这种运算法则编译器已经写好了(必须有一个自定义类型

 

 

 

 

11 双目运算符重载

 

全局函数:

注意:这里最好写引用Complex &,不是直接写Complex

 

a+=b+=c  这个双目运算符的计算  (a+=(b+=c))

如果之前写法没有引用的话

虽然是正确的

但是返回的是匿名临时对象 然后把匿名临时对象的值给真实的C1

最好是写引用的写法 直接修改C1

 

 

成员函数:只能写一个参数

 

 

12单目运算符重载前++和- -

 

 

全局函数:

 

成员函数:

 

 

13 单目运算符后++

 

占位操作符

// 亚元

 

a++ // 单目运算符

 

全局函数:

 

成员函数:

 

 

 

14操作符重载输入输出操作符

 

比如我想把虚数cout出来:

原理:

<< 这个双目运算符传入cout 和 c12

 

(报错显示:没有找到重载)

 

展开找一下cout和cin的类型

 

重写:

 

加上连等功能:

 

 

(普通双目操作符的成员函数操作符重载)

 

cin操作符重载:

 

15等号操作符

 

定义一下深拷贝浅拷贝:

浅拷贝,直接复制一份和原来一样的(结果导致里面可能有相同的引用

深拷贝,按逻辑的复制一份新的

 

 

 

当执行s3=s1的时候,

 

有个两个问题:

  1. li4泄露了
  2. zhangsan重复释放

 

等号操作符默认也是浅拷贝,但是相比拷贝构造有一个风险,

即:当调用拷贝构造函数的时候,一定是初始化,

但当调用等号操作符的时候,可能里面已经有值了,所以应该判断一下,如果有值就释放掉

 

 

代码:

 

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

 

using namespace std;

 

 

class Student

{

public:

    Student(int id,const char *name)

    {

        this->id = id;

 

        int len = strlen(name);

        this->name = (char*)malloc(len + 1); // 将name在堆上开辟一个空间

        strcpy(this->name, name);

    }

 

    // 防止浅拷贝 提供一个显示的拷贝构造函数 

    Student (const Student & another_s)

    {

        this->id = another_s.id;

        int len = strlen(another_s.name);

        this->name = (char *)malloc(len + 1);

        strcpy(this->name, another_s.name);

    }

 

    // 重写等号操作符

    // 返回值用引用来实现连等

    Student & operator=(const Student & another_s)

    {

        if (this->name != NULL)

        {

            // 原来有数据 需要释放

            delete[] this->name;

            this->name = NULL;

            this->id = 0;

        }

        // 到这为止,之前的数据释放完毕

        this->id = another_s.id;

        int len = strlen(another_s.name);

        this->name = (char *)malloc(len + 1);

        strcpy(this->name, another_s.name);

 

        return *this;

       

    }

 

 

    ~Student()

    {

        if (this->name != NULL)

        {

            delete[] this->name;

            this->name = NULL;

            this->id = 0;

        }

 

    }

    void printS()

    {

        cout << "id: " << this->id << ", name = " << this->name << endl;

    }

private:

    int id;

    char *name; // 准备在堆上开辟空间

}   ;

 

 

int main(void)

{

 

 

    Student s1(1, "张三");

    Student s2(s1); // 当你调用拷贝构造的时候,一定是初始化

 

    Student s3(2, "李四"); // 已经有内存分配了

    s3 = s1; // 不是调用拷贝构造 //编译器也给我们提供了一个默认的=操作符

     

    s1.printS();

 

    return 0;

}

 

 

posted @ 2019-03-11 21:17  hh9515  阅读(366)  评论(0编辑  收藏  举报