c++教程2021-6-17学习笔记

/**
 *一个类是另外一个类的成员属性,构造函数和析构函数的执行顺序。
 * 1。构造函数,先执行其他类的构造,再执行本类构造。
 * 2。析构函数和构造函数的执行顺序正好相反。
 */

class Phone {

public :

    string p_Name;

    Phone() {
        cout << "Phone 默认构造函数执行。" << endl;
    }

    Phone(string pName) : p_Name(pName) {
        cout << "Phone 有参构造函数执行。" << endl;
    }

    ~Phone() {
        cout << "Phone 析构函数执行。" << endl;
    }

};


class Person113 {

public:
    string m_Name;
    Phone p_Name;
    //再这里有一个隐示转化,Phone p_Name = pName; 这里就是通过隐示调用构造其他类有参构造函数进行。
    //也就是上面的 Phone(string pName) : p_Name(pName) 构造函数。
    Person113(string name, string pName) : m_Name(name), p_Name(pName) {
        cout << "Person 构造函数执行。" << endl;
    }
    ~Person113() {
        cout << "Person 析构函数执行。" << endl;
    }


};

void test() {
    Person113 p("张三", "苹果");
}


int main() {
    test();
    return 0;
}
/**
 * 静态成员函数:
 * 1.所有的对象都共享一个函数。
 * 2.静态成员函数,只能访问静态成员变量。
 *
 */

class Person114 {

public:
    //静态函数
    static void func() {
        m_Age = 10;
//        m_Num = 20;//不允许访问非静态变量。
        cout << "静态函数被调用" << endl;
    }

    //普通函数
    void func2() {
        cout << "静态函数被调用" << endl;
    }

    static int m_Age ;
    int m_Num;

};

void test() {
    Person114 p;
    p.func(); //这是通过对象的方式调用。
    Person114::func();//通过类名来访问。
}

int main() {
    test();
    return 0;
}
/**
 *c++中对象模型和指针:
 *1.c++编译器会给每一个空对象,分配一个字节的空间
 *2.只有成员变量的数据会保存在对象上,其他的都不会保存在对象上。
 */

class Person115{

    int m_A;//非静态成员变量。属于对象上。
    static int m_B;//静态成员函数,不属于对象上。
    void func(){//非静态成员函数,不属于对象上。
    }
    static void func2(){//静态成员函数,不属于对象上。
    }
};

int Person115::m_B=0;

void test(){
    Person115 p;
    cout << sizeof (p)<<endl;//这里输出是1,c++编译器默认分配空对象是1。如果对象中没有任何数据。
}

void test01(){
    Person115 p;
    cout << sizeof (p)<<endl;//这里输出是4,因为有一个int 的4个字节。
}

int main(){
    test01();
    return 0;
}

/**

  • this 指针:指向被调用成员函数所属的对象。
  • 大白话,就是谁调用它,它就指向哪个对象。如果想返回对象本身,就return *this; 对this 进行解引用。
  • c++ 是允许空指针调用成员函数。 只要里面没有引用this 就不会报错。 如果对this 做了判空处理,也可以调用。见例子test03()
    */

```cpp
class Person115{

public :
    int age;

    Person115(int age){
        this->age = age;//this 指向的是谁调用它就是指向谁。
    }

    void addAge(const Person115 &person115){
        this->age += person115.age; //这个函数,不能进行累加。链式编程
    }
    //链式累加。返回对象本身,这里注意,不能返回Person115值,那么这里就会调用copy 构造函数,每次生成一个新的Person115对象。
    Person115 &linkAddAge(const Person115 &person115){
        this->age += person115.age;
        return *this;
    }

    void showClassName(){
        cout << "Person115 class"<<endl;
    }
    void showClassAge(){
        cout << "Person115 showClassAge:"<<this->age<<endl;
    }
};

void test(){
    Person115 person115(18);
    cout << person115.age<<endl;
}

void test01(){
    Person115 person115(10);
    person115.addAge(person115);
    cout << person115.age<<endl;
}

void test02(){
    Person115 person115(10);
    person115.linkAddAge(person115).linkAddAge(person115).linkAddAge(person115);
    cout << person115.age<<endl;
}

void test03(){
    Person115 * person115 = NULL;
    person115->showClassName();//空指针是可以调用这个函数。
    person115->showClassAge(); //这里会报错。因为调用age的时候,需要通过this->调用,this=NUll。
}


int main(){
//    test();
//    test01();
//    test02();
    test03();
    return 0;
}
/**
 * const 修饰成员函数:成为常函数。如果想修改这个对象属性,那么加入mutable
 * const 修饰对象,叫做常对象,常对象只能调用常函数。
 */

class Person118 {

public:
    Person118() {

    }

    void showAge() const { //这个就相当于const Person118 * const this; 常量指针常量。都不允许修改。
        //在函数后面加入const 修饰的是this 指针。让this指向的值不修改。
        //this->m_Age = 100;
        this->m_B = 100;//加入了mutable 之后,即是在常函数中,也可以修改。
//        this = NULL;//this 也是一个指针常量。this 是不允许被修改的。但是this 指向的值是可以修改的。
//上面这句话的理解为:Person118 * const this;是一个指针常量。
    }

    void func() {

    }

    int m_Age;
    mutable int m_B;

};


void test() {
    const Person118 p;
    //常对象。也不允许修改这个对象的值。常对象只能调用常函数。
    // 如果调用普通函数,那么有可能在普通函数中修改其对应的属性值。
    p.m_B = 100;
//    p.m_Age = 100;//这里不允许被修改。
    p.showAge(); //ok,没有问题。常对象调用常函数。
//    p.func();//不允许调用普通函数。如果在func里面修改值是不允许的。
}


int main() {
    test();
    return 0;
}
/**
 * 友元:friend 就是声明一些特殊的函数活着类,来访问另一个类的私有成员。
 * 友元的三种实现:
 * 1.全局函数做友元。
 * 2.类做友元。
 * 3.成员函数做友元。
 */

//1.全局函数做友元。
class Building{

    //这里是关键,让全局函数作为友元函数。这样其他的类就可以访问Building里面的私有成员。
    friend  void goodGay(Building &building);
public:
    Building(){
        m_SittingRoom = "客厅";
        m_BedRoom = "卧室";
    }
public:
    string m_SittingRoom;
private:
    string m_BedRoom;
};

void goodGay(Building &building){
    cout<<"访问的是:"<< building.m_SittingRoom<<endl;
    cout<<"访问的是:"<< building.m_BedRoom<<endl;//理论上是不能访问Building的私有成员。这里作为友元函数可以访问。

}

void test(){
    Building building;
    goodGay(building);
}

int main(){
    test();
    return 0;
}



/**
 * 友元:friend 就是声明一些特殊的函数活着类,来访问另一个类的私有成员。
 * 友元的三种实现:
 * 1.全局函数做友元。
 * 2.类做友元。
 * 3.成员函数做友元。
 */

//2.类做友元
class Building{
    //这句话的意思是,让GoodGay类能访问Building 类的私有成员。
    friend class GoodGay;
public :
    Building();
    string m_SittingRoom;
private :
    string m_BedRoom;
};

class GoodGay{
public:
    GoodGay();
    Building *building;
    void visit();
    GoodGay(const GoodGay &goodGay){
        building = goodGay.building;
    }
    ~GoodGay(){
        if(building != NULL){
            delete building;
            building = NULL;
        }
    }
};

//在类外进行构造函数初始化
Building::Building() {
    m_SittingRoom = "客厅";
    m_BedRoom = "卧室";
}

//在类外进行构造函数初始化
GoodGay::GoodGay() {
    building =  new Building();
}


void GoodGay::visit() {
    cout<<"GoodGay访问"<<building->m_SittingRoom<<endl;
    cout<<"GoodGay访问"<<building->m_BedRoom<<endl;
}

void test(){
    GoodGay goodGay;
    goodGay.visit();
}

int main(){
    test();
    return 0;
}

//3.成员函数做友元。
class Building{
    //这句话的意思是,GoodGay::visit成员方法能访问Building 类的私有成员。
    friend void GoodGay::visit();
public :
    Building();
    string m_SittingRoom;
private :
    string m_BedRoom;
};

class GoodGay{
public:
    GoodGay();
    Building *building;
    void visit();
    GoodGay(const GoodGay &goodGay){
        building = goodGay.building;
    }
    ~GoodGay(){
        if(building != NULL){
            delete building;
            building = NULL;
        }
    }
};



/**
 * 运算符重载:
 * +号运算符重载
 */

class Person {
public:
    int m_A;
    int m_B;
    //1.通过成员函数重载+
//    Person operator+(Person &person){
//        Person temp ;
//        temp.m_A = this->m_A+person.m_A;
//        temp.m_B = this->m_B + person.m_B;
//        return  temp;
//    }
};

//2.通过全局函数重载+
Person operator+(Person &p1, Person &p2) {
    Person temp;
    temp.m_A = p1.m_A + p2.m_A;
    temp.m_B = p1.m_B + p2.m_B;
    return temp;
}

//2.通过全局函数重载+
Person operator+(Person &p1, int num) {
    Person temp;
    temp.m_A = p1.m_A + num;
    temp.m_B = p1.m_B + num;
    return temp;
}

void test() {
    Person p1;
    Person p2;
    Person p3;
    p1.m_A = 10;
    p1.m_B = 10;
    p2.m_A = 10;
    p2.m_B = 10;
    p3 = p1 + p2;
    cout << p3.m_A << endl;
    cout << p3.m_B << endl;
    Person p4;
    p4 = p1 + 100; //这里可以做运算符重载。
    cout << p4.m_A << endl;
    cout << p4.m_B << endl;
}

int main() {
    test();
    return 0;
}


/**
 *<<左移运算符
 * >>右移运算符
 */

//左移运算符,只能通过全局函数重载。
class Person122 {
    friend ostream & operator<<(ostream  &cout,Person122 &p);
public:
    Person122(int a,int b):m_A(a),m_B(b){
    }
private :
    int m_A;
    int m_B;
};

ostream & operator<<(ostream  &cout,Person122 &p){
     cout<<"Person A:"<< p.m_A << "    Person B:"<< p.m_B;
     return cout;
}

void test(){
    Person122 p(10,10);
    cout << p <<endl;
}
int main() {
    test();
    return 0;
}




/**
 *重载++运算符,有前置++ 和后置++
 */

class MyInteger {
    friend ostream &operator<<(ostream &cout, MyInteger &myInteger);
public:
    MyInteger() {
        m_Num = 0;
    }
    //前置++操作
    MyInteger & operator++(){
        this->m_Num++;
        return *this;
    }

    //后置++操作,参数中的int 占位符代表的是后置++
     MyInteger operator++(int){
        MyInteger temp  = *this; //保存临时变量
        m_Num++; //对进行++操作。
        return temp;//返回临时保存的变量。
    }

private:
    int m_Num;
};

//重载<<左移运算符
ostream &operator<<(ostream &cout, MyInteger &myInteger) {
    cout << myInteger.m_Num;
    return cout;
}


void test(){
    MyInteger myInteger;
    cout << ++myInteger<<endl;
    cout << myInteger<<endl;
}
void test01(){
    MyInteger myInteger;
    MyInteger myInteger1 = myInteger ++;
    cout << myInteger1 <<endl;
    cout << myInteger <<endl;
}
int main() {
    test();
    test01();
    return 0;
}



//重载赋值运算符。
class Person125{
    friend void test();
public:
    Person125(int age){
        m_Age = new int(age);
    }

    //重载=运算符。首先清空本身的内存,然后再申请内存。
    Person125 & operator=(Person125 &p){ 
        if(m_Age != NULL){
            delete m_Age;
            m_Age = NULL;
        }
        m_Age = new int(*p.m_Age);
        return *this;
    }


    ~Person125(){//析构函数
        if(m_Age != NULL){
            delete m_Age;
            m_Age = NULL;
        }
    }
private :
    int * m_Age;
};

void test(){
    Person125 p1(18);
    Person125 p2(28);
    Person125 p3(38);

    p3=p2=p1;//这里存在浅copy的问题。需要重载=运算符
    cout<<*p1.m_Age<<endl;
    cout<<*p2.m_Age<<endl;
    cout<<*p3.m_Age<<endl;
}


int main(){
    test();
    return 0;
}


//关系运算符。> < !=  == 等等。
class Person126{
public:
    Person126(string name,int age):m_Name(name),m_Age(age){

    }

    bool operator==(Person126 &p){
        if(this->m_Name == p.m_Name && this->m_Age == p.m_Age){
            return true;
        }
        return false;
    }
    bool operator!=(Person126 &p){
        if(this->m_Name == p.m_Name && this->m_Age == p.m_Age){
            return false;
        }
        return true;
    }
private :
    string m_Name;
    int m_Age;
};

void test(){
    Person126 p1("Tom",18);
    Person126 p2("Tom",18);

    if(p1 == p2){
        cout<< "相等"<<endl;
    }else{
        cout<< "不相等"<<endl;
    }
}


int main(){
    test();
    return 0;
}



//函数调用运算符重载(),也称之为仿函数,在STL中经常被使用。

//类名+() 匿名对象

class MyPrint{

public:
    //这是重载(),也称之为仿函数
    void operator()(string test){
        cout << test<< endl;
    }
};

class MyAdd{
public:
    int operator()(int a,int b){
        return a+ b;
    }
};
int main(){
    MyPrint myPrint ;
    myPrint("你好");//这里使用相当于函数一样。所以称之为仿函数
    //通过函数名+()的形式是匿名对象,用完即销毁。
    int ret = MyAdd()(10,20);
    cout << ret<<endl;
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值