• Ⅰ 类与对象④


    4.静态成员

    class CPoint2D
    {
        float x, y;
        const float num;   //存在资源浪费现象,经常会重复
    };                    
    
    CPoint2D aaa,bbb;    //有好多。。。
    sizeof(aaa) == 12 ==sizeof(bbb);

    4.1 定义

    不同对象之间数据成员和函数的共享,使其在内存中只有一个对应的存储区域

     4.2 用法

    class CPoint2D
    {
        float x, y;
        static int num;   //升级为静态成员
    public:
        CPoint2D()
        {
            x = y = 0;
            num++;
        } 
        CPoint2D(float x, float y)
        {
            this->x = x;
            this->y = y;
            num++;
        } 
        ~CPoint2D()
        {
            num--;
        } 
        static int GetCounter()
        {
            return num;          //不能输出x,y
        }
    };
    int CPoint2D::num = 0;  //初始化,推荐在类外进行初始化
    int main()
    {
        CPoint2D v0, v1;
        int num1, num2;
        num1 = CPoint2D::GetCounter();  //可以通过类名直接调用
        num2 = v0.GetCounter();   //通过对象调用
    }

    4.3 注意

    ◼ 静态成员变量的初始化使用“类名::静态成员变量名”的形式

    ◼ 在建立对象之前通过类就可操作静态成员

    ◼ 静态成员函数中没有this指针,不能直接访问类中的非静态成员变量

    5.友元

    5.1 定义

    ◼ 非本类的成员函数(或外部函数)如何访问类中的私有成员(保护成员) ??(设置访问控制属性为public → 彻底破坏类的封装性和隐藏性) 

    ◼ 友元:包括友元函数和友元类
    ◼ 友元不是类的成员,但能够访问类中被隐蔽的信息

    5.2 友元函数

    class A
    {
    private:
        int i ;
        void MemberFun(int) ;
        friend void FriendFun(A*, int) ;  //友元函数的声明
    } ;
    //友元函数的定义
    void FriendFun(A* ptr, int x )  //与全局函数类似,在类外定义时无::
    {
        ptr -> i = x ;     //不能通过i=x直接访问成员变量,必须通过参数传递,访问私有成员
    }                      //没有this指针
    void A::MemberFun( int x )  //普通的在类里面的函数必须要有域操作符
    {
        i = x ;
    }

    5.2.1 应用——求两点间的距离

    class CPoint2D
    {
         float x, y;
    public:
         CPoint2D()
        {
            x = y = 0;
        }
        CPoint2D(float x, float y)
        {
            this->x = x;
            this->y = y;
        }
        friend float Distance(CPoint2D p1, CPoint2D p2);
    };
    
    float Distance(CPoint2D p1, CPoint2D p2)
    {
        float dx = p1.x - p2.x;   //友元函数不能直接访问成员变量,
    但可以通过参数传递操作对象中的所有成员
    float dy = p1.y - p2.y; return sqrt(dx * dx + dy * dy ) ; } int main() { CPoint2D v0(1,1), v1(4,5); cout<<Distance(v0,v1)<<endl; return 0; }

    ◼ An ordinary member function declaration specifies three logically distinct things: [1] The function can access the private part of the class declaration, 可以访问类中的私有成员

    [2] the function is in the scope of the class, 在类中{  。。。}

    [3] the function must be invoked on an object (has a this pointer).Class A{ };A a;a.draw();对象可以调用类中的函数  

    By declaring a member function static, we can give it the first two properties only. By declaring a function a friend, we can give it the first property only.

    5.2.2 前向引用声明

    class B;      //A使用之前,B还没出现,编译器按顺序来的话,会判错
    class A{     //给个提示,我后面会有B滴!( ̄︶ ̄*))
    public: 
        void funA(B b); 
    };
    
    class B{
     public: 
        void funB(A b); 
    };

    5.3 友元类

    一般的没法访问,不方便 

     CCircle可以使用我啦!但我不可以使用CCircle

    ◼ 友员关系是非传递的

    Y类是X类的友员,Z类是Y类的友员,但Z类不一定是X类的友员

    ◼ 友员关系是单向的
    若Y类是X类的友员,则Y类的成员函数可以访问X 类的私有和保护成员,反之则不然

    ◼ 友员提高了数据的共享性,但在一定程度上削弱了数据的隐藏性

    6.常对象与常成员

     6.1 常对象

     6.2 常数据成员

     6.3 常成员函数

     ◼ 进行类设计时,建议遵循以下两点:

    1. 将不涉及数据成员修改的函数定义为常成员函数,形如:

    int CPoint2D::GetX() const;
    2. 函数调用时,若希望传入的实参对象不被修改,应将形参定义为const类型的指针或引用;实参可以是const类型的,也可以是非const类型的,函数接口兼容性更好,形如:

    void TransByPointer(const CPoint2D* obj) {

    cout << "TransByPointer" << endl;

    }

    void TransByRefence(const CPoint2D& obj) {

    cout << "TransByRefence" << endl;

    }

    7.对象的内存分布

    7.1 内存分布

    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    class CPoint2D
    {
        int x, y;
        static int num;
    public:
        CPoint2D()         //默认构造函数
        {        x = y = 0;
            num++;    }
        CPoint2D(int x, int y)   //带形参的构造函数
        {        this->x = x;
            this->y = y;
            num++;    }
        ~CPoint2D()         //析构函数
        {        num--;        }
        static int GetCounter()   //静态函数
        {        return num;     }
        float GetX()       //普通函数
        {        return x;    }
        void Output()
        {        cout << "静态变量地址:" << &num << endl;
            cout << "静态函数地址:" << (void *)&GetCounter << endl;    }
    };
    
    int CPoint2D::num = 0;  //静态数据成员初始化
    CPoint2D g_v(1,1);  //全局对象
    
    int main()
    {
        CPoint2D v;  //局部对象
        CPoint2D *p;  //局部对象指针
    
        p = new CPoint2D;  //才有了真正的内存,调用了构造函数 
        p->GetCounter();
    
        cout << "全局对象地址:" << &g_v << endl;
        cout << "局部对象地址:" << &v << endl;
        cout << "动态对象地址:" << p << endl;
    p
    ->Output(); cout << "局部对象函数地址:" << (void *)&(v.GetX) << endl; cout << "全局对象函数地址:" << (void *)&(g_v.GetX) << endl; cout << "动态对象函数地址:" << (void *)&(p->GetX) << endl; cout << "main函数地址:" << (void *)&main << endl; delete p; }

    全局对象地址:0x4c600c      数据段:全局&静态
    局部对象地址:0x6dfed4       栈区:临时对象&变量(局部对象、参数传递)
    动态对象地址:0x711210      堆区:新建的存储空间,动态分配
    静态变量地址:0x4c6008
    静态函数地址:0x4387b8      代码段:成员函数&静态函数
    局部对象函数地址:0x4387c4
    全局对象函数地址:0x4387c4
    动态对象函数地址:0x4387c4
    main函数地址:0x401350

     

     7.2 对象的生命周期

    #include <iostream>
    #include <string>
    using namespace std;
    
    class base
    {
        string mark;
    public:
        base()
        {
            mark = "null";
            cout << "Constructor " << mark << endl;
        }
        base(string str)    //对象的成员函数的内存空间在该类的所有对象
        {                        //生命周期结束时自动释放
            mark = str;
            cout << "Constructor " << mark << endl;
        }
        ~base()
        {
            cout << "Destructor " << mark << endl;
        }
    };
    
    base g1("g1");  //全局对象的生命(占有的内存空间)在程序结束时释放
    base g2("g2");
    int main()
    {
        base l1("l1"); //局部对象,当对象生成时,其构造函数被执行;当程序流程将离开该对象的声明周期时,其析构函数被执行。
        base l2("l2");
        base *d1, *d2;
        d1 = new base("d1");  //动态建立的内存空间一定要用delete释放
        d2 = new base ("d2");
        delete d1;    //若没有,d1、d2的空间一直占用
        delete d2;
        return 0;
    }

     7.3 对象构造函数与析构函数调用顺序

     例2:形状类的设计

    #include <iostream>
    #include <graph2d.h>
    #include <cmath>
    #include <vector>
    
    using namespace std;
    using namespace graph;
    
    class CPoint2D      //点类
    {
        float x, y;        //属性:坐标
    public:
        CPoint2D()      //坐标初始化为0  
        {
            x = y = 0;
        }
        CPoint2D(float x, float y)   //也可以自己修改坐标
        {
            this->x = x;
            this->y = y;
        }
        void Translate(float x, float y)   //移动
        {
            this->x = this->x + x;
            this->y = this->y + y;
        }
        void Scale(float r)        //缩放
        {
            x = r*x;
            y = r*y;
        }
        friend class CTriangle;     //在这些形状里都可以使用
        friend class CRectangle;
        friend class CEllipse;
        friend class CDonut;
    };

    class CRectangle
    {
        CPoint2D center;  //友元类
        float len;
        float wid;
        ULONG color;
    public:
        CRectangle():center(CPoint2D(400,300)),  
        len(300), wid(200), color(0xBBE0E3) {}   //默认
        CRectangle(CPoint2D w, float len, float wid,    //初始化
                   ULONG color = 0xBBE0E3):center(w)
        {
            this->len = len;
            this->wid = wid;
            this->color = color;
        }
        void Translate(float x, float y)
        {        center.Translate(x, y);    }
        void Draw()
        {
            CPoint2D v1(center.x-len/2, center.y+wid/2);  //求出需要的
            CPoint2D v2(center.x+len/2, center.y-wid/2);
            setColor(color);
            fillRectangle(v1.x, v1.y, v2.x, v2.y); //真正的操作
            setColor(BLACK);
            rectangle(v1.x, v1.y, v2.x, v2.y);
        }
        void Scale(float r)
        {        center.Scale(r);
            len = len*r;
            wid = wid*r;    }
    };
    
    class CEllipse
    {
        CPoint2D center;
        float xRadius;
        float yRadius;
        ULONG color;
    public:
        CEllipse():center(CPoint2D(400,300)),
          xRadius(150), yRadius(100), color(0xBBE0E3) {}
        CEllipse(CPoint2D w, float len, float wid,
                  ULONG color = 0xBBE0E3):center(w)
        {
            this->xRadius = 0.5*len;
            this->yRadius = 0.5*wid;
            this->color = color;
        }
        void Translate(float x, float y)
        {        center.Translate(x, y);    }
        void Draw()
        {
            setColor(color);
            fillEllipse(center.x, center.y, xRadius, yRadius);
            setColor(BLACK);
            ellipse(center.x, center.y, xRadius, yRadius);
        }
        void Scale(float r)
        {        center.Scale(r);
            xRadius = xRadius*r;
            yRadius = yRadius*r;    }
    };
    
    class CDonut
    {
        CPoint2D center;
        float xRadius;
        float yRadius;
        float ratio;
        ULONG color;
    public:
        CDonut():center(CPoint2D(400,300)),
        xRadius(150), yRadius(100), ratio(0.5), color(0xBBE0E3) {}
        CDonut(CPoint2D w, float rx, float ry, float r,
                ULONG color = 0xBBE0E3):center(w)
        {
            this->xRadius = rx;
            this->yRadius = ry;
            this->ratio = r;
            this->color = color;
        }
        void Translate(float x, float y)
        {        center.Translate(x, y);    }
        void Draw()
        {
            setColor(color);
            fillDonut(center.x, center.y, xRadius, yRadius, ratio);
            setColor(BLACK);
            donut(center.x, center.y, xRadius, yRadius, ratio);
        }
        void Scale(float r)
        {        center.Scale(r);
            xRadius = xRadius*r;
            yRadius = yRadius*r;    }
    };
    
    class CTriangle
    {
        CPoint2D center;
        float len;
        float wid;
        ULONG color;
    public:
        CTriangle():center(CPoint2D(400,300)),
          len(300), wid(200), color(0xBBE0E3) {}
        CTriangle(CPoint2D w, float len, float wid,
                   ULONG color = 0xBBE0E3):center(w)
        {
            this->len = len;
            this->wid = wid;
            this->color = color;
            cout << len << ", " << wid << endl;
        }
        void Translate(float x, float y)
        {        center.Translate(x, y);    }
        void Draw()
        {
            CPoint2D v1(center.x-len/2, center.y-wid/2);
            CPoint2D v2(center.x+len/2, center.y-wid/2);
            CPoint2D v3(center.x, center.y+wid/2);
            setColor(color);
            fillTriangle(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y);
            setColor(BLACK);
            triangle(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y);
        }
        void Scale(float r)
        {   center.Scale(r);     len = len*r;        wid = wid*r;    }
    };
    绘制图形
    vector <CTriangle> g_vTri;            //有很多的数据,数组
    
    bool ReadShapes()
    {
        float length, width, r, rx, ry, wx, wy;
        ULONG objCol;
        string sel;
    
        cin >> sel;
        while (sel != "Exit")
        {
            if (sel == "Triangle")
            {
                cin >> wx >> wy >> length >> width >> hex >> objCol >> dec;
                g_vTri.push_back(CTriangle(CPoint2D(wx, wy), length, width, objCol));
            }
            else
            {
                cout << "Error reading!" << endl;
                return false;
            }
            cin >> sel;
        }
    
        return true;
    }
    
    void display()
    {
        for(size_t i=0; i<g_vRect.size(); i++)
            g_vRect[i].Draw();
    }
    
    void keyboard(unsigned char key)
    {
        switch (key)
        {
        case 'w':
            for(size_t i=0; i<g_vTri.size(); i++)
                g_vTri[i].Translate(0, 5);
            break;
        case 's':
            for(size_t i=0; i<g_vTri.size(); i++)
                g_vTri[i].Translate(0, -5);
            break;
        case 'a':
            for(size_t i=0; i<g_vTri.size(); i++)
                g_vTri[i].Translate(-5, 0);
            break;
        case 'd':
            for(size_t i=0; i<g_vTri.size(); i++)
                g_vTri[i].Translate(5, 0););
            break;
        }
    }
    
    /*
    Rectangle    400    400    800    400    0xC0E8F2
    Rectangle    400    100    800    200    0xB8BD95
    Rectangle    407    354    30    100    0x8C1926
    Ellipse    403    425    15    15    0xFFEEEE
    Ellipse    360    480    20    20    0xFFEEEE
    Ellipse    300    550    30    30    0xFFEEEE
    Rectangle    474    181    236    200    0xDECA8F
    Triangle    474    340    340    180    0x9E6120
    Rectangle    412    227    30    30    0xB5C9EE
    Rectangle    550    227    30    30    0xB5C9EE
    Rectangle    412    130    30    30    0xB5C9EE
    Rectangle    550    130    30    30    0xB5C9EE
    Rectangle    474    167    80    20    0xF9B06B
    Rectangle    462    128    25    55    0x8C1926
    Rectangle    486    128    25    55    0x8C1926
    Rectangle    474    94    80    12    0x9F9E99
    Rectangle    474    82    100    12    0x9F9E99
    Ellipse    444    45    50    15    0x9F9E99
    Ellipse    322    31    55    18    0x9F9E99
    Ellipse    181    22    65    15    0x9F9E99
    Rectangle    154    78    10    15    0x814000
    Triangle    154    103    95    50    0x002800
    Triangle    154    131    85    45    0x002800
    Triangle    154    156    70    40    0x002800
    Triangle    154    184    50    50    0x002800
    Rectangle    254    78    10    15    0x814000
    Triangle    254    103    95    50    0x002800
    Triangle    254    131    85    45    0x002800
    Triangle    254    156    70    40    0x002800
    Triangle    254    184    50    50    0x002800
    Donut    474    490    80    60    0.5    0x814000
    Exit
    */
    
    int main()
    {
        ReadShapes();
        initGraph(display, keyboard);
        return 0;
    }
  • 相关阅读:
    D-Power Products
    B2
    软考知识点梳理--螺旋模型
    软考知识点梳理--敏捷方法
    软考知识点梳理--瀑布模型
    软考知识点梳理--统一软件开发过程RUP
    软考知识点梳理--信息系统生命周期
    软考知识点梳理--信息资源管理
    软考知识点梳理--以太网
    软考知识点梳理--应急储备与管理储备
  • 原文地址:https://www.cnblogs.com/syzyaa/p/12701325.html
Copyright © 2020-2023  润新知