mooc程序设计与算法(三)C++面向对象程序设计 类和对象提高

this指针

this 指针,作用是指向成员函数所作用的对象

非静态成员函数中可以直接使用this代表指向该函数作用的对象的指针

静态成员函数中不能使用this指针,因为静态成员函数并不作用于某一个具体的对象

静态成员函数真实的参数个数与写出的个数一样,普通函数多一个,就是this指针

#include <iostream>
using namespace std;
class A{
    int i;
public:
    void pri(){
        cout<<"hello"<<endl;
    }
};
int main()
{
    A a;
    a.pri();
    return 0;
}

这个例子会输出”hello”,说明调用了pri函数,但是没有对a初始化,因为this指针相当于调用了

void pri(A *this){cout<<"hello"<<endl;}

这样一句话。。。。但是如果输出i的值,会出错

静态成员

在说明前面加了static加了关键字的成员

sizeof不会计算静态成员变量

静态成员遍历,为所有的对象共享

静态成员函数并不具体作用于某个对象

静态成员不需要对象就能访问

静态成员变量(函数)是全局变量(函数),那怕一个对象都不存在,它也存在

为什么引入?因为把和某些类相关的变量和函数写进类,便于维护

静态成员函数中,不能访问非静态成员变量和函数。

#include <iostream>
using namespace std;
class CRectangle
{
private:
    int w, h;
    static int nTotalArea;//静态成员变量
    static int nTotalNumber;

public:
    CRectangle(int w_, int h_){
        //构造函数
        w=w_;
        h=h_;
        nTotalNumber++;
        nTotalArea+=w*h;
    };
    ~CRectangle(){
        //析够函数
        nTotalArea-=w*h;
        nTotalNumber--;
        cout<<endl<<"destruct "<<w<<" "<<h<<endl;
    };
    CRectangle(const CRectangle &c){
        //复制构造函数
        h = c.h+1;
        w = c.w+1;
        nTotalNumber++;
        nTotalArea += h*w;
    }
    void pri(){
        cout<<endl<<"w is:"<<w<<" h is:"<<h<<endl;
    }
    static void PrintTotal(){
        cout<<endl<<nTotalNumber<<" "<<nTotalArea;
    };
};
//注意,静态成员变量要在类外边进行声明,要不然会报错
int CRectangle::nTotalNumber=0;
int CRectangle::nTotalArea=0;

int main()
{
    CRectangle r1(2,2), r2(3,3);
    CRectangle r3(r2);
    CRectangle::PrintTotal();//输出

    r1.PrintTotal();//输出
    r3.pri();
    return 0;
}

结果(注意析够函数):

3 29
3 29
w is:4 h is:4

destruct 4 4

destruct 3 3

destruct 2 2

成员对象和封闭类

有成员对象的类叫做封闭类

先执行成员函数的构造函数,在执行封闭类的构造函数

成员对象的构造函数调用次序和对象成员在类中的说明次序一致,与初始化列表无关

封闭类消亡的时候,先指向封闭类的析够函数,在执行成员对象的析够函数。次序和构造函数的调用相反(构造和析够相反的)。

#include <iostream>
using namespace std;
class CTyre
{
private:
    int radius;
    int width;
public:
    CTyre(int r, int w):radius(r), width(w){
        cout<<endl<<"in CTyre constructor"<<endl;
    }
    void pri(){
        cout<<"in ctyre:"<<radius<<" "<<width<<endl;
    };
    ~CTyre(){
        cout<<endl<<"in ctyre destructor"<<endl;
    }
};
class CEngine
{
public:
    CEngine(){
        cout<<endl<<"in CEngine constructor"<<endl;
    }
    ~CEngine(){
        cout<<endl<<"in CEnigne destructor"<<endl;
    }
};
class CCar{
    //封闭类
private:
    int price;
    CTyre tyre;//成员对象
    CEngine engine;
public:
    CCar(int p, int tr, int tw):price(p), tyre(tr, tw){
        cout<<endl<<"in CCar constructor"<<endl;
    }//初始化列表
    void print(){
        tyre.pri();
    }
    ~CCar(){
        cout<<endl<<"in CCar destructor"<<endl;
    }
};
int main()
{
    CCar car(1,2,3);
    car.print();
    return 0;
}

结果:

in CTyre constructor

in CEngine constructor

in CCar constructor
in ctyre:2 3

in CCar destructor

in CEnigne destructor

in ctyre destructor

封闭类和复制构造函数

#include <iostream>
using namespace std;
class A{
public:
    A(){
        cout<<"default"<<endl;
    }
    A(const A&a){
        cout<<"in A copy"<<endl;
    }
};
class B{
    A a;
public:
    B(){
        cout<<"in B copy"<<endl;
    }
};
int main()
{
    B b1, b2(b1);
    return 0;
}
default
in B copy
in A copy

常量对象、常量成员函数和常引用

如果不希望某个对象的值被改变,则定义该对象的时候,可以在前面加上const关键字

常量成员函数执行奇迹不应修改其作用的对象,因此,常量成员函数中不能修改成员变量的值(静态成员变量除外),也不能调用同类的非常量成员函数(静态成员函数除外)。

#include <iostream>
using namespace std;
class Sample
{
private:
    static int v;
public:
    int value;

    void GetValue() const;
    void func(){}
    Sample(){}
    void print(){
        cout<<v<<endl;
    }
};
void Sample::GetValue() const {
    //value=0//error
    v++;
}

int Sample::v=0;
int main()
{
    Sample s;
    s.GetValue();
    s.print();
    return 0;
}

结果是:1
说明,常量成员函数可以修改静态成员遍历

友元

友元分为友元函数和友元类

一个类的友元函数(有可能是全局函数)可以访问这个类的私有成员

如果A是B的友元类,那么A的成员函数可以访问B的私有成员。

友元类之间的关系不能传递,不能继承。

#include <iostream>
using namespace std;
class CCar;
class CDriver{
public:
    void ModifyCar(CCar *pCar);
};
class CCar{
private:
    int price;
    friend int MostExpensiveCar(CCar cars[], int total);
    friend void CDriver::ModifyCar(CCar *pCar);

public:
    void set_price(int p){
        price=p;
    }
};
void CDriver::ModifyCar(CCar *pCar) {
    pCar->price+=1000;//注意,这里访问了CCar类的私有成员
}
int MostExpensiveCar(CCar cars[], int total){
    int tmpMax=-1;
    for (int i = 0; i < total; ++i) {
        if(cars[i].price>tmpMax) tmpMax=cars[i].price;
    }
    return tmpMax;
}
int main()
{
    CCar c1, c2;
    c1.set_price(12);
    c2.set_price(13);
    CCar cars[2]={c1, c2};
    cout<<MostExpensiveCar(cars, 2);
    return 0;
}

结果

13

猜你喜欢

转载自blog.csdn.net/abc15766228491/article/details/79877623