15_类和对象

类和对象

成员函数类内实现

#include <iostream>
#include<string.h>

using namespace std;

class Person
{
private:
    char mName[32];
    int mAge;
public:
    void personInit(char *name, int age)
    {
        strcpy(mName, name);
        if(age > 0 && age < 200)
        {
            mAge = age;
        }
        else {
            cout << "年龄错误" << endl;
        }
    }

    void setName(char *name)
    {
        strcpy(mName, name);
    }

    char *getName()
    {
        return mName;
    }

    void setAge(int age)
    {
        mAge = age;
    }

    int getAge()
    {
        return mAge;
    }

    void showPerson()
    {
        cout << "姓名: " << mName << ", 年龄: " << mAge << endl;
    }
};

int main(int argc, char *argv[])
{
    Person lucy;
    lucy.personInit("lucy", 18);
    lucy.showPerson();
    return 0;
}

成员函数类外实现

#include <iostream>

using namespace std;

class Data
{
private:
    int mA;
public:
    //类中声明
    void setA(int a);
    int getA();
};

//类外实现
void Data::setA(int a)
{
    mA = a;
}

int Data::getA()
{
    return mA;
}

int main(int argc, char *argv[])
{
    Data data;
    data.setA(5);
    cout << data.getA() << endl;
    return 0;
}

类在其他源文件中实现

data.h

#ifndef DATA_H
#define DATA_H

class Data
{
private:
    int mA;
public:
    void setA(int a);
    int getA();
};

#endif // DATA_H

data.cpp

#include "data.h"

void Data::setA(int a)
{
    mA = a;
}

int Data::getA()
{
    return mA;
}

main.cpp

#include <iostream>
#include<data.h>

using namespace std;

int main(int argc, char *argv[])
{
    Data data;
    data.setA(50);
    cout << data.getA() << endl;
    return 0;
}

构造函数

class Data
{
    public:
    	int mA;
    	Data() //无参构造函数
        {
            mA = 0;
            cout << "无参构造函数" << endl;
        }
    	Data(int a) //有参构造函数
        {
            mA = a;
            cout << "有参构造函数 mA = " << mA << endl;
        }
};
void main()
{
    //隐式调用无参构造函数(推荐)
    Data ob1;
    
    //显示调用无参构造函数
    Data ob2 = Data();
    
    //隐式调用有参构造函数(推荐)
    Data ob3(10);
    
    //显示调用有参构造函数
    Data ob4 = Data(10);
    
    //匿名对象(无参) 当前语句技术 立即释放
    Data();
    Data(20);
    
    //构造函数隐式转换 (类中只有一个数据成员)
    Data ob5 = 100; //Data ob5(100)
}

析构函数

函数名和类名称相同, 在函数名前加~, 没有返回值类型, 没有函数形参(不能被重载)

当对象生命周期结束时系统自动调用析构函数

先调用析构函数,再释放对象空间

class Data1
{
    public int mA;
    	int mA;
    public:
    	//无参构造函数
        Data1()
        {
			mA = 0;
            cout << "无参构造函数" << endl;
        }
    
    	//有参构造函数
    	Data1(int a)
        {
            mA = a;
            cout << "有参构造函数 mA = " << mA << endl;
        }
    
    	//析构函数
    	~Data1()
        {
            cout << "析构函数 mA = " << mA << endl;
        }
}

一般情况下, 系统默认会空的析构函数就已足够, 但是如果一个类有指针成员, 那必须写析构函数,释放指针成员指向的空间

data.h

#ifndef DATA_H
#define DATA_H
#include<iostream>
#include<string.h>
using namespace std;
class Data
{
private:
    int mA;
    char *name;
public:
    Data();
    Data(int a, char *name);
    ~Data();
    void setA(int a);
    void setName(char *name);
    int getA();
    char *getName();
    void toString();
};

#endif // DATA_H

data.cpp

#include "data.h"

Data::Data()
{
    name = NULL;
    cout << "无参构造函数" << endl;
}

Data::Data(int a, char *name)
{
    setA(a);
    setName(name);
    cout << "有参构造函数" << endl;
}

Data::~Data()
{
    if(name != NULL)
    {
        delete[] name;
    }
    cout << "析构函数" << endl;
}

void Data::setA(int a)
{
    mA = a;
}

void Data::setName(char *name)
{
    Data::name = new char[strlen(name+1)];
    strcpy(Data::name, name);
}

int Data::getA()
{
    return mA;
}

char *Data::getName()
{
    return name;
}

void Data::toString()
{
    cout << "mA: " << mA << " ,name: " << name << endl;
}

main.cpp

#include <iostream>
#include"data.h"

using namespace std;

int main()
{
    char p[] = "hdl";
    Data d1(5, p);
    d1.setA(50);
    d1.toString();
    return 0;
}

delete 运算符用于删除使用 new 运算符或 NULL 指针分配的指针,而 free() 函数用于删除使用 malloc()、calloc() 或 realloc() 分配的指针函数或void指针。

拷贝构造函数

Data d1;
Data d2 = d1; //拷贝构造函数

拷贝对象定义形式

Data(const Data &d2) //常引用
{
	
}

系统默认的拷贝构造函数可以完成浅拷贝

拷贝构造的几种调用形式

旧对象给新对象初始化 调用拷贝构造

Data ob1(10);
Data ob2 = ob1; //调用拷贝构造

给对象取别名 不会调用拷贝构造

Data ob1(10);
Data &ob2 = ob1; //不会调用拷贝构造

普通对象作为函数参数 调用函数时会发生拷贝构造

void func(Data ob) //Data ob = ob1
{
    
}
void main()
{
    Data ob1(100); //有参构造
    func(ob1); //拷贝构造
}

函数返回值普通对象

VsCode中的编辑器:
Data getObject()
{
    Data ob1(10);
    return ob1; //return ob1 到栈区的临时区 发生拷贝构造
}
void main()
{
    Data ob2 = getObject();
}

image-20230929150115959

image-20230929154727260

Qt Creator , Linux中的编辑器:

image-20230929154815664

Qt Creator , Linux中做了优化, 在getObject()返回时不会创建临时空间拷贝构造函数, 而是直接将该对象的空间返回

拷贝构造的浅拷贝和深拷贝

默认的拷贝构造都是浅拷贝。如果类中没有指针成员,不用实现拷贝构造和析构函数。如果类中有指针成员,且指向堆区空间,必须实现析构函数释放指针成员指向的堆区空间,必须实现拷贝构造完成深拷贝动作。

data.h

#ifndef DATA_H
#define DATA_H
#include<string.h>
#include<iostream>

using namespace std;

class Data
{
private:
    char *name;
public:
    Data();
    Data(char *name);
    Data(const Data &d);
    ~Data();
};

#endif // DATA_H

data.cpp

#include "data.h"

Data::Data() //无参构造
{

}

Data::Data(char *name) //有参构造
{
    Data::name = new char[strlen(name)+1];
    strcpy(Data::name, name);
    cout << "有参构造" << endl;
}

Data::Data(const Data &d) //拷贝构造
{
    name = new char[strlen(name)+1];
    strcpy(name, d.name);
    cout << "拷贝构造" << endl;
}

Data::~Data() //析构
{
    delete[] name;
    cout << "析构" << endl;
}

main.cpp

#include <iostream>
#include"data.h"

using namespace std;

int main()
{
    char name[] = "hhh";
    Data d1(name);
    Data d2 = d1;
    return 0;
}

初始化列表

对象成员

在类中定义的数据成员一般都是基本的数据类型。但是类中的成员也可以是对象,叫做对象成员。

先调用对象成员的构造函数,再调用本身的构造函数。析构函数和构造函数调用顺序相反,先构造,后析构

类会自动调用对象成员的无参构造

初始化列表

类想调用成员对象的有参构造必须使用初始化列表

class A{
private:
	int mA;
public:
	A(int a)
    {
        mA = a;
    }
};
class B
{
private:
    A ob;
public:
    B(int a):ob(a) //会调用A的有参构造
    {
        
    }
};

explicit 关键字

c++提供了关键字explicit,禁止通过构造函数进行的隐式转换。声明为explicit的构造函数不能在隐式转换中使用。

注意explicit用于修饰构造函数,防止隐式转化。 是针对单参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造)而言。

class A
{
public:
    explicit A(int a)
    {
        
    }
}
void main()
{
    A a = 5; //error
    A a(5); //ok
}

explicit 会禁止 A a = 5; 这种写法

类的对象数组

本质是数组, 数组中的元素是对象

void main()
{
    //对象数组不初始化, 每个元素会调用无参构造和析构
    A arr1[5]; 
    //对象数组初始化
    A arr2[5] = {A(10), A(20), A(30), A(40), A(50)};
}

动态对象创建

new 创建动态对象

C++中解决动态内存分配的方案是把创建一个对象所需要的操作都结合在一个称为new的运算符里。当用new创建一个对象时,它就在堆里为对象分配内存并调用构造函数完成初始化。

Person* person = new Person; //无参

delete释放动态对象

delete先调用析构函数再释放内存

void main()
{
    Person* person = new Person("josn", 20); //有参
    person->toString();
    delete person;
}

动态对象数组

Person* persons = new Person[20];
delete[] persons

静态成员

静态成员变量

image-20230930155548864

static修饰的成员 定义类时必须分配空间

static修饰的静态成员数据必须再类中定义类外初始化

class Data
{
public:
    int a;
    //类中定义
    static int b;
};
//类外初始化
int Data::b = 10; //不要再加static

静态成员函数

class Data
{
private:
    int data;
    static int a;
public:
    static int getA() 
    {
        data = 10; //error 静态成员函数只能操作静态成员变量
        return a;
    }
};
int Data::a = 100;

单例模式

#include <iostream>

using namespace std;

class SingleTon //单例模式
{
private:
    static SingleTon *const p; //const防止p在类内部被修改指向
    //构造私有化, 防止实例化其他对象
private:
    SingleTon(){}
    SingleTon(const SingleTon &ob){}
    ~SingleTon(){}
public:
    static SingleTon *getSingleTon() //获取唯一实例地址
    {
        return p;
    }
    void fun()
    {
        cout << "执行任务" << endl;
    }
};

SingleTon *const SingleTon::p = new SingleTon;

int main()
{
    SingleTon *p1 = SingleTon::getSingleTon();
    p1->fun();
    return 0;
}

C++面向对象模型

成员变量和函数存储

class Data
{
public:
    char a;
    int b;
    static int c;
    void fun(){}
};
void main()
{
    size(Data); //大小只是a+b(类的对象所占大小)
}

image-20231001155317824

this指针

image-20231001155623340

this指针指向被调用的成员函数所属的对象

静态成员函数内部没有this指针

image-20231001160234213

const 修饰成员函数

用const修饰的成员函数时,const修饰this指针指向的内存区域,成员函数体内不可以修改本类中的任何普通成员变量,当成员变量类型符前用mutable修饰时例外

class Data
{
public:
    int a;
    int b;
    mutable int c;
public:
    Data(int a, int b, int c)
    {
        this->a = a;
        this->b = b;
        this->c = c;       
    }
    //const修饰成员函数为只读(不允许对成员数据赋值, mutable除外)
    void showData() const
    {
        //a = 10; //error
        c = 100; //ok
    }
}

友元

有时需要在类的外部访问类的私有成员,就可以使用友元函数

友元的语法

使用friend关键字在声明处

普通全局函数作为类的友元

class Room
{
    friend void visiting01(Room &room);
private:
    string bedRoom; //卧室
public:
    string setingRoom; //客厅
public:
    Room(string bedRoom, string setingRoom)
    {
        this->bedRoom = bedRoom;
        this->setingRoom = setingRoom;
    }
};
//普通全局函数
void visiting01(Room &room)
{
    cout << "访问了: " << room.setingRoom << endl;
    cout << "访问了: " << room.bedRoom << endl; 
}
void main()
{
    Room room("卧室", "客厅");
    visiting01(room);
}

类中的某个成员函数作为另一个类的友元

class Room; //声明
class goodGay
{
public:
    void visiting01(Room &room);
    void visiting02(Room &room);
};
class Room
{
    friend void goodGay::visiting02(Room &room);
private:  
    string bedRoom; //卧室
public:
    string setingRoom; //客厅
public:
    Room(string bedRoom, string setingRoom)
    {
        this->bedRoom = bedRoom;
        this->setingRoom = setingRoom;
    }
};
void goodGay::visiting01(Room &room)
{
    cout << "访问了: " << room.setingRoom << endl;
}
void goodGay::visiting02(Room &room)
{
    cout << "好基友张三访问了: " << room.setingRoom << endl;
    cout << "好基友张三访问了: " << room.bedRoom << endl;
}
void main()
{
    Room room("卧室", "客厅");
    goodGay ob;
    ob.visiting01(room);
    ob.visiting02(room);
}

整个类作为 另一个类的友元

这个类的所有成员函数都可以访问另一个类的私有数据

class Room; //声明
class goodGay
{
public: 
    void visiting01(Room &room);
    void visiting02(Room &room);
};
class Room
{
    friend class goodGay;
private:
    string bedRoom;
public:
    string setingRoom;
public:
    Room(string bedRoom, string setingRoom)
    {
        this->bedRoom = bedRoom;
        this->setingRoom = setingRoom;
    }
};
void goodGay::visiting01(Room &room)
{
    cout << "访问了: " << room.setingRoom << endl;
    cout << "访问了: " << room.bedRoom << endl;
}
void goodGay::visiting02(Room &room)
{
    cout << "访问了: " << room.setingRoom << endl;
    cout << "访问了: " << room.bedRoom << endl;
}
void main()
{
    Room room("卧室", "客厅");
    goodGay ob;
    ob.visiting01(room);
    ob.visiting02(room);
}

友元注意事项

1友元不能被继承

2友元关系是单向的, 类A是类B的朋友, 但B不一定是A的朋友

3友元关系不具有传递性, 类B是类A的朋友, 类C是B的朋友, 但C不一定是A的朋友

设计电视和遥控器类


#include <iostream>

using namespace std;

class TV; //声明提前

//遥控器的类作为TV的友元
class Remote //遥控器
{
private:
    TV *p;
public:
    Remote(TV *p);
    void offOrOn();
    void upVolume();
    void downVolume();
    void upChannel();
    void downChannel();
    void showTv();
    void setChannel(int channel);
};

class TV //电视机
{
    friend Remote;
    enum{OFF, ON};
    enum{minVol, maxVol = 10};
    enum{minChan, maxChan = 25};
private:
    int state;
    int volume;
    int channel;
public:
    TV()
    {
        state = OFF;
        volume = minVol;
        channel = minChan;
    }

    void offOrOn();
    void upVolume();
    void downVolume();
    void upChannel();
    void downChannel();
    void showTv();

};

void TV::offOrOn()
{
    state = (state == OFF ? ON:OFF);
}

void TV::upVolume()
{
    if(volume == maxVol)
    {
        cout << "音量已经最大" << endl;
    }
    else{
        volume++;
    }
}

void TV::downVolume()
{
    if(volume == minVol)
    {
        cout << "音量已经最小" << endl;
    }
    else{
        volume--;
    }
}

void TV::upChannel()
{
    if(channel == maxChan)
    {
        cout << "频道已经最大" << endl;
    }
    else{
        channel++;
    }
}

void TV::downChannel()
{
    if(channel == minChan)
    {
        cout << "频道已经最小" << endl;
    }
    else{
        channel--;
    }
}

void TV::showTv()
{
    cout << "当前电视机状态: " << (state == OFF?"关":"开") << endl;
    cout << "当前音量: " << volume << endl;
    cout << "当前频道: " << channel << endl;
}

int main()
{
    TV tv;
    Remote re(&tv);
    re.offOrOn();
    re.upVolume();
    re.setChannel(29);
    re.showTv();
    return 0;
}

Remote::Remote(TV *p)
{
    this->p = p;
}

void Remote::offOrOn()
{
    p->offOrOn();
}

void Remote::upVolume()
{
    p->upVolume();
}

void Remote::downVolume()
{
    p->downVolume();
}

void Remote::upChannel()
{
    p->upChannel();
}

void Remote::downChannel()
{
    p->downChannel();
}

void Remote::showTv()
{
    p->showTv();
}

void Remote::setChannel(int channel)
{
    if(channel >= TV::minChan && channel <= TV::maxChan)
    {
        p->channel = channel;
    }
    else
    {
        cout << "频道" << channel << "不在选择范围内!" << endl;
    }
}

运算符重载

重载<<运算符(全局函数实现)

#include <iostream>
#include<string>

using namespace std;

class Person
{
    friend ostream& operator<<(ostream &out, Person &ob);
private:
    int num;
    string name;
    float score;
public:
    Person(){}
    Person(int num, string name, float score): num(num), name(name), score(score){}
};

//全局函数重载operator<<
ostream& operator<<(ostream &out, Person &ob)
{
    out << ob.num << " " << ob.name << " " << ob.score;
    return out;
}

int main()
{
    Person lucy(1, "lucy", 98);
    Person bob(2, "bob", 85);
    cout << lucy << endl << bob <<endl;
    return 0;
}

重载>>运算符(全局函数实现)

#include <iostream>
#include<string>

using namespace std;

class Person
{
    friend ostream& operator<<(ostream &out, Person &ob);
    friend istream& operator>>(istream &in, Person &ob);
private:
    int num;
    string name;
    float score;
public:
    Person(){}
    Person(int num, string name, float score): num(num), name(name), score(score){}
    int getNum()
    {
        return num;
    }
};

//全局函数重载operator<<
ostream& operator<<(ostream &out, Person &ob)
{
    out << ob.num << " " << ob.name << " " << ob.score;
    return out;
}

//全局函数重载operator>>
istream& operator>>(istream &in, Person &ob)
{
    in >> ob.num >> ob.name >> ob.score;
    return in;
}

int main()
{
    Person lucy;
    Person bob;
    cin >> lucy >> bob;
    cout << lucy << endl;
    cout << bob << endl;
    return 0;
}

可以重载的运算符

image-20231004191247079

重载+运算符(全局函数实现)

#include <iostream>
#include<string>
using namespace std;

class Person
{
    friend istream& operator>>(istream& in, Person& ob);
    friend ostream& operator<<(ostream& out, Person ob);
    friend Person operator+(Person &ob1, Person &ob2);

private:
    int num;
    string name;
    float score;
public:
    Person(){}
    Person(int num, string name, float score):num(num), name(name), score(score){}
};

istream& operator>>(istream& in, Person& ob)
{
    in >> ob.num >> ob.name >> ob.score;
    return in;
}

ostream& operator<<(ostream& out, Person ob)
{
    out << ob.num << " " << ob.name << " " << ob.score;
    return out;
}

//全局函数重载+运算符
Person operator+(Person &ob1, Person &ob2)
{
    Person tmp;
    tmp.num = ob1.num + ob2.num;
    tmp.name = ob1.name + ob2.name;
    tmp.score = ob1.score + ob2.score;
    return tmp; //引用不能对局部对象使用
}

int main()
{
    Person lucy;
    cin >> lucy;
    Person bob;
    cin >> bob;
    cout << lucy+bob << endl;
    return 0;
}

重载+运算符(成员函数实现 推荐)

#include <iostream>
#include<string>
using namespace std;

class Person
{
    friend istream& operator>>(istream& in, Person& ob);
    friend ostream& operator<<(ostream& out, Person ob);
    friend Person operator+(Person &ob1, Person &ob2);

private:
    int num;
    string name;
    float score;
public:
    Person(){}
    Person(int num, string name, float score):num(num), name(name), score(score){}
    //成员函数重载+运算符
    Person operator+(Person& ob)
    {
        Person tmp;
        tmp.num = num + ob.num;
        tmp.name = name + ob.name;
        tmp.score = score + ob.score;
        return tmp;
    }
};

istream& operator>>(istream& in, Person& ob)
{
    in >> ob.num >> ob.name >> ob.score;
    return in;
}

ostream& operator<<(ostream& out, Person ob)
{
    out << ob.num << " " << ob.name << " " << ob.score;
    return out;
}

int main()
{
    Person lucy;
    cin >> lucy;
    Person bob;
    cin >> bob;
    cout << lucy.operator+(bob)<< endl;
    return 0;
}

重载==运算符(成员函数实现 推荐)

#include <iostream>
#include<string>
#include<string.h>

using namespace std;

class Person
{
    friend istream& operator>>(istream& in, Person& ob);
    friend ostream& operator<<(ostream& out, Person ob);
    friend Person operator+(Person &ob1, Person &ob2);

private:
    int num;
    string name;
    float score;
public:
    Person(){}
    Person(int num, string name, float score):num(num), name(name), score(score){}
    //成员函数重载==运算符
    bool operator==(Person& ob)
    {
        if(num == ob.num && name == ob.name && score == ob.score)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

};

int main()
{
    Person lucy(101, "lucy", 95.8);
    Person bob(101, "lucy", 95.8);
    if(lucy == bob)
    {
        cout << "相等" << endl;
    }
    else
    {
        cout << "不相等" << endl;
    }
    return 0;
}

重载++/--运算符

重载的++和--运算符有点让人不知所措,因为我们总是希望能根据它们出现在所作用对象的前面还是后面来调用不同的函数。解决办法很简单,例如当编译器看到++a(前置++),它就调用operator++(a),当编译器看到a++ (后置++) ,它就会去调用operator++(a,int).

++a -> operator++(a)

a++ -> operator++(a, int)

--a -> operator--(a)

a-- -> operator--(a, int)

重载a++

#include <iostream>
#include<string>
#include<string.h>

using namespace std;

class Person
{
    friend istream& operator>>(istream& in, Person& ob);
    friend ostream& operator<<(ostream& out, Person ob);
    friend Person operator+(Person &ob1, Person &ob2);

private:
    int num;
    string name;
    float score;
public:
    Person(){}
    Person(int num, string name, float score):num(num), name(name), score(score){}
    //重载a++
    Person operator++(int)
    {
        //保存旧值
        Person old = *this;
        //++
        num++;
        name = name+name;
        score++;
        return old;
    }

};

istream& operator>>(istream& in, Person& ob)
{
    in >> ob.num >> ob.name >> ob.score;
    return in;
}

ostream& operator<<(ostream& out, Person ob)
{
    out << ob.num << " " << ob.name << " " << ob.score;
    return out;
}

int main()
{
    Person lucy(101, "lucy", 95.8);
    lucy++;
    cout << lucy << endl;
    return 0;
}

重载++a

#include <iostream>
#include<string>
#include<string.h>

using namespace std;

class Person
{
    friend istream& operator>>(istream& in, Person& ob);
    friend ostream& operator<<(ostream& out, Person ob);
    friend Person operator+(Person &ob1, Person &ob2);

private:
    int num;
    string name;
    float score;
public:
    Person(){}
    Person(int num, string name, float score):num(num), name(name), score(score){}
    //成员函数重载==运算符
    bool operator==(Person& ob)
    {
        if(num == ob.num && name == ob.name && score == ob.score)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    //重载++a
    Person operator++()
    {
        num++;
        name = name+name;
        score = score+1;
        return *this;
    }

};

istream& operator>>(istream& in, Person& ob)
{
    in >> ob.num >> ob.name >> ob.score;
    return in;
}

ostream& operator<<(ostream& out, Person ob)
{
    out << ob.num << " " << ob.name << " " << ob.score;
    return out;
}

int main()
{
    Person lucy(101, "lucy", 95.8);
    Person bob;
    bob = ++lucy;
    cout << bob << endl;
    cout << lucy << endl;
    return 0;
}

设计MyString案例

#include <iostream>
#include <string.h>

using namespace std;

class MyString
{
    friend ostream& operator<<(ostream& out, MyString ob);
    friend istream& operator>>(istream& in, MyString& ob);
private:
    char* str;
    int size;
public:
    MyString();
    MyString(char* str);
    MyString(const MyString &ob);
    ~MyString();
    int getSize();
    //成员函数重载[]运算符
    char& operator[](int pos);
    //成员函数重载+运算符
    MyString operator+(MyString& ob);
    MyString operator+(char* str);
    //重载赋值运算符(只有指针成员operator=必须深拷贝)
    MyString& operator=(MyString& ob);
    MyString& operator=(char* str);
    //重载>运算符
    bool operator>(MyString& ob);
    bool operator>(char* str);
};

//全局函数重载<<运算符
ostream& operator<<(ostream& out, MyString ob)
{
    out << ob.str;
    return out;
}

//全局函数重载>>运算符
istream& operator>>(istream& in, MyString& ob)
{
    char buff[128] = "";
    in >> buff;
    if(ob.str != NULL)
    {
        memset(ob.str, 0, ob.size+1);
    }
    ob.size = strlen(buff);
    ob.str = new char[ob.size+1];
    memset(ob.str, 0, ob.size+1);
    strcpy(ob.str, buff);
    return in;
}

int main()
{
//    MyString str1 = "hello";
//    cout << str1[1] << endl;
//    str1[1] = 'H';
//    cout << str1[1] << endl;
//    cout << str1 << endl;
//    cin >> str1;
//    cout << str1 << endl;
//    MyString str2 = "hello";
//    MyString str3 = "world";
//    cout << str2+str3 << endl;
//    cout << str2+"hdl" << endl;
//    MyString str1("hello");
//    MyString str2("world");
//    MyString str3("!");
//    str1 = str2 = str3;
//    cout << str1 << endl;
    MyString str1("hello");
    MyString str2("world");
    if(str1 > str2)
    {
        cout << "大于" << endl;
    }
    else
    {
        cout << "小于等于" << endl;
    }
    return 0;
}

MyString::MyString()
{
    str = NULL;
    size = 0;
}

MyString::MyString(char *str)
{
    this->str = new char[strlen(str)+1];
    memset(this->str, 0, strlen(str)+1);
    size = strlen(str);
    strcpy(this->str, str);
}

MyString::MyString(const MyString &ob)
{
    size = ob.size;
    str = new char[size+1];
    memset(str, 0, size+1);
    strcpy(str, ob.str);
}

MyString::~MyString()
{
    if(str != NULL)
    {
        delete[] str;
        str == NULL;
    }
}

int MyString::getSize()
{
    return size;
}

char& MyString::operator[](int pos)
{
    if(pos<0 || pos>=size)
    {
        cout << "下标越界" << endl;
        exit(-1);
    }
    return str[pos];
}

MyString MyString::operator+(MyString& ob)
{
    MyString tmp;
    tmp.size = size + ob.size;
    tmp.str = new char[tmp.size+1];
    memset(tmp.str, 0, sizeof(char)*(tmp.size+1));
    strcpy(tmp.str, str);
    strcat(tmp.str, ob.str);
    return tmp;
}

MyString& MyString::operator=(MyString &ob)
{
    if(str!=NULL)
    {
        delete[] str;
        str = NULL;
    }
    str = new char[ob.size+1];
    memset(str, 0, ob.size+1);
    strcpy(str, ob.str);
    size = ob.size;
    return *this;
}

bool MyString::operator>(MyString &ob)
{
    if(str==NULL || ob.str==NULL){
        exit(-1);
    }
    if(strcmp(str, ob.str) > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool MyString::operator>(char* str)
{
    if(this->str==NULL || str==NULL){
        exit(-1);
    }
    if(strcmp(this->str, str) > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

MyString& MyString::operator=(char* str)
{
    if(this->str!=NULL)
    {
        delete[] this->str;
        this->str = NULL;
    }
    this->str = new char[strlen(str)+1];
    memset(this->str, 0, strlen(str)+1);
    strcpy(this->str, str);
    size = strlen(str);
    return *this;
}

MyString MyString::operator+(char* str)
{
    MyString tmp;
    tmp.size = size + strlen(str);
    tmp.str = new char[tmp.size+1];
    memset(tmp.str, 0, sizeof(char)*(tmp.size+1));
    strcpy(tmp.str, this->str);
    strcat(tmp.str, str);
    return tmp;
}

重载函数调用运算符

重载()运算符 一般用于为算法 提供策略

当对象和()结合 会触发 重载函数调用运算符

#include <iostream>

using namespace std;

class Print
{
public:
    //重载函数调用运算符
    void operator()(char* str)
    {
        cout << str << endl;
    }
};

int main()
{
    Print ob;
    //对象和()结合触发operator()调用
    ob("hello Print");
    
    //Print()匿名对象
    Print()("hello print");
    return 0;
}

智能指针(指针运算符(*, ->)重载)

#include <iostream>

using namespace std;

class Data
{
public:
    Data()
    {
        cout << "Data的无参构造" << endl;
    }
    ~Data()
    {
        cout << "Data的析构函数" << endl;
    }
    void func()
    {
        cout << "Data的func函数" << endl;
    }
};

//智能指针
class SmartPointer
{
private:
    Data *p;
public:
    SmartPointer(){}
    SmartPointer(Data *p){
        this->p = p;
    }
    ~SmartPointer()
    {
        delete p;
    }
    //重载->运算符
    Data* operator->()
    {
        return p;
    }
    //重载*运算符
    Data& operator*()
    {
        return *p;
    }
};

int main()
{
//    Data *p = new Data;
//    p->func();
//    //不调用delete就不会释放
//    delete p;
    SmartPointer sp(new Data);
    sp->func();
    (*sp).func();
    return 0;
}

不要重载&& ||

因为无法实现短路特性

posted @ 2023-10-05 21:36  爱吃冰激凌的黄某某  阅读(7)  评论(0编辑  收藏  举报