C++(5) encapsulation, classes and objects

Package Encapsulation

Multiple types can be packaged into one to form a new type.

The encapsulation style of C language puts data together and packs struct

Then pass the data to the behavior by reference or pointer

#include <iostream>

using namespace std;

struct Man
{
    string name;
    int age;
    char sex;
    float high;
    float salary;
};

struct Date
{
    int year;
    int month;
    int day;
};

//封装成函数
void init(Date d)
{
    cin>>d.year;
    cin>>d.month;
    cin>>d.day;
}

void print(Date & d)
{
    cout<<"year: "<<d.year<<" month: "<<d.month<<" day: "<<d.day<<endl;
}

bool isLeapYear(Date & d)
{
    if(d.year % 4 == 0 && d.year % 100 != 0 || d.year % 400 == 0)
        return true;
    else
        return false;
}

int main()
{
    Date d;  //定义变量,开辟空间
    init(d);
    print(d);

    if(isLeapYear(d))
        cout<<d.year<<" is leap year"<<endl;
    else:
        cout<<d.year<<" is not leap year"<<endl;

    return 0;
}

C++ thinks that C language encapsulation is not thorough

Data and behavior classification, no permission control. Open to internal data, logical abstraction. Provide an interface to the outside world.

Declaration and implementation should be separated, use class

#include <iostream>

using namespace std;

//权限控制 private protected public
//数据和行为在一起
//对内开放数据,逻辑抽象
//对外提供接口

class Date
{
public:
    void init()
    {
        cin>>year;
        cin>>month;
        cin>>day;
    }
    int getYear()
    {
        cout<<year<<endl;
    }
    void print()
    {
        cout<<"year:"<<"month:"<<"day:"<<endl;
        cout<<year<<":"<<month<<":"<<day<<endl;
    }
protected:
    int year;
    int month;
    int day;
};

int main()
{
    Date d;
    // d.year = 3000;

    d.print();

    return 0;
}
#include <iostream>

using namespace std;

class Date
{
public:
    void init();  // 类函数成员
    void print();
    int getYear();
    bool isLeapYear();
private:
    int year;  //数据成员 
    int month;
    int day;
}

void init()  //全局
{

}

class BB
{
public:
    void init();
}

void Date::init()
{
    cin>>year;
    cin>>month;
    cin>>day;
}

void BB::init()
{

}

int main()
{
    return 0;
}

The class name is actually a disguised namespace

Example: stack

stack.h

#ifndef STACK_H
#define STACK_H

class Stack
{
public:
    void init();
    bool isEmpty();
    bool isFull();
    char pop();
    void push(char c);
private:
    char space[1024];
    int top;
}

#endif // STACK_H

stack.cpp

#include "stack.h"
#include <iostream>
#include <stdlib.h>
#include <string.h>

void Stack::init()
{
    top = 0;
    memset(space, 0, 1024);
}

bool Stack::isEmpty()
{
    return top == 0;
}

bool Stack::isFull()
{
    return top == 1024;
}

char Stack::pop()
{
    return space[--top];
}

void Stack::push(char c)
{
    space[top++] = c;
}

main.cpp

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

using namespace std;

int main()
{
    Stack st;
    st.init();

    for(char v = 'a'; !st.isFull() && v != 'z'; v++)
    {
        st.push(v);
    }

    while(!st.isEmpty())
        cout<<st.pop()<<endl;

    return 0;
}

Written in a file main.cpp

#include <iostream>
#include <stdlib.h>

using namespace std;

class Stack
{
public:
    void init();
    bool isEmpty();
    bool isFull();
    char pop();
    void push(char c);
private:
    char space[1024];
    int top;
};

void init(Stack & s)
{
    s.top = 0;
    memset(s.space, 0, 1024);
}

bool isEmpty(Stack & s)
{
    return s.top == 0;
}

bool isFull(Stack & s)
{
    return s.top == 1024;
}

char pop(Stack & s)
{
    return s.space[--s.top];
}

char push(Stack & s, char c)
{
    s.space[s.top++] = c;
}

int main()
{
    Stack st;
    init(st);

    if(!isFull())
        push(st, 'a');

    while(!isEmpty(st))
        cout<<pop(st)<<endl;

    return 0;
}

constructor, destructor

constructor constructor

1. Same as the class name, no return value, automatically called when the system generates an object, used for initialization

2. There can be parameters, constructor overloads, and default parameters. Overload and default cannot exist at the same time

3. If no constructor is provided, the system will generate an empty constructor with no parameters by default. If provided no default initializer is generated

#ifndef STACK_H
#define STACK_H

class Stack
{
public:
    Stack()  //无参构造
    {
        top = 0;
        space = new char[1000];
    }
    Stack(int size)  //有参构造
    {
        top = 0;
        space = new char[size];
        _size = size;
    }
    void init();
    bool isEmpty();
    bool isFull();
    char pop();
    void push(char c);

    ~Stack()
    {
        cout<<""<<endl;
    }

private:
    char space[1024];
    int top;
    int size;
}

#endif // STACK_H

destructor destructor

1. ~ is the same as the class name, no parameters, no return, and will be called automatically when the object disappears.

2. It is used for memory processing when objects are destroyed.

3. If not provided, the system is sure to generate an empty destructor.

Example: building a clock

#include <iostream>
#include <time.h>
#include <iomanip>
#include <unistd.h>

using namespace std;

//初始化的数据来自系统,以后的逻辑运算及显示自实现

class Clock
{
public:
    Clock()
    {
        time_t t = time(NULL);
        struct tm ti = *localtime(&t);  //获得系统时间 struct tm *__cdecl localtime(const time_t * _Time)

        hour = ti.hour;
        min = ti.min;
        sec = ti.sec;
    }

    void run()
    {
        while(1)
        {
            show();  // 完成显示
            tick();  // 数据更新
        }
    }

private:
    void show()
    {
        system("clear");
        cout<<setw(2)<<setfill('0')<<hour<<":";
        cout<<setw(2)<<setfill('0')<<min<<":";
        cout<<setw(2)<<setfill('0')<<sec;
    }
    void tick()
    {
        sleep(1);
        if(++sec == 60)
        {
            sec = 0;
            if(++min == 60)
            {
                min = 0;
                if(hour == 24)
                {
                    hour = 0;
                }
            }
        }
    }

    int hour;
    int min;
    int sec;
};

int main()
{
    Clock c;
    c.run();
    return 0;    
}

const modifier

1. const modifies data members, member functions, and class objects

2. When modifying data members, the initialization position can only be in the parameter list

Data members modified by const cannot be modified

3. Modified member functions

Position: After the function declaration, before the function implementation body

Meaning: const function promises not to modify data members

Can access const and non-const data members, but cannot modify non-const data members

Only const member functions can be accessed.

composition overload

A const object can only call const member functions.

For non-const member objects, call non-const member functions first, if not, then call const member functions.

4. Decorate objects

The const modified function is from the level of the function and does not modify the data.

The const modified object is from the object level, without modifying the data, only const member functions can be called.

#include <iostream>

using namespace std;

class A
{
public:
    A(int v)
        :val(v)
    {
    }
    
    void dis()
    {
        cout<<val<<endl;
    }
    void dis() const
    {
        cout<<"void dis() const"<<endl;
    }

private:
    const int val;
};

int main()
{
    A a;
    a.dis();

    return 0;
}

Static

Global variables Extensive static Scope: limited to this file Life cycle, storage location

local variable auto

The performance of static inside the class is used to realize data sharing between family objects

When generating objects, ordinary data members have space. The static member has already opened up space (in the data rw segment) when the class is declared.

The essence of a class is also a namespace

1. Initialization Defined within the class, initialized outside the class. type class name::variable name = initial value

2. Static data members belong to both classes and objects, but ultimately belong to classes

3. Static modified member functions, because they belong to a class, have no this pointer, and cannot access non-static data members and member functions

#include <iostream>

using namespace std;

//static 修饰成员函数,作用只用于管理static成员

class School
{
public:
    string & getTower()
    {
        return power;
    }
    static string & getLib()
    {
        return lib;
    }
private:
    string power;
    string lake;
    static string lib;
};

string School::lib = "aaaaa";  // 初始化静态数据成员,否则报错——C++无法解析的外部符号

int main()
{
    School::getLib() = "aa";
    School::getLib() += "bb";

    School cz, bn, blue;
    cz.getTower() = "aaa";
    bn,getTower() = "bbb";
    blue.getTower() = "ccc";

    cz.getLib() += "ddd";
    bn.getLib() += "eee";
    blue.getLib() += "fff";

    cout<<cz.getLib()<<endl;
    cout<<bn.getLib()<<endl;
    cout<<School::getLib()<<endl;

    return 0;
}
#include <iostream>

using namespace std;

class CCSprite
{
public:
    CCSprite(int d)
    {
        data = d;
        if(head == NULL)
        {
            this->next = NULL;
            head = this;
        }
        else
        {
            this->next = head->next;
            head = this;
        }
    }

    static void traverseCCSprite()
    {
        CCSprite * ph = head;
        while(ph != NULL)
        {
            cout<<ph->data<<endl;
            ph = ph->next;
        }
    }

private:
    int data;
    CCSprite * next;
    static CCSprite * head;
};

CCSprite * CCSprite::head = NULL;  //在外边初始化

int main()
{
    CCSprite a(1), b(2), c(3);
    for(int i = 100; i < 100; i++)
        new CCSprite(i);
    
    CCSprite::traverseCCSprite();
    return 0;
}

point to class member

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

using namespace std;

class Stu
{
    Stu(string sn, int ia):
        name(sn), age(ia){}

    void print()
    {
        cout<<name<<"--"<<age<<endl;
    }

public:
    string name;
    int age;
};

int main()
{
    Stu s1("aaa", 39);
    Stu s2("bbb", 79);

    string Stu::* pn = &Stu::name;

    cout<<s1.name<<s2.name<<endl;
    cout<<s1.*pn<<s2.*pn<<endl;  // .* 

    return 0;
}
#include <iostream>

using namespace std;

class Widget
{
public:
    Widget()
    {
        pa[0] = &f;
        pa[1] = &g;
        pa[2] = &i;
        pa[3] = &j;
    }

    void select(int idx)
    {
        (this->*pa[idx])();
    }

private:
    void f() {cout<<"void f()"<<endl;}
    void g() {cout<<"void g()"<<endl;}
    void i() {cout<<"void i()"<<endl;}
    void j() {cout<<"void j()"<<endl;}

    enum {cnt = 4};
    void (Widget::*pa[cnt])() = {f, g, i, j};
};

//指向类成员函数的指针

int main()
{
    Widget w;
    w.select(0);

    return 0;
}

Friend breaks encapsulation

member function to friend function

#include <iostream>
#include <math.h>

using namespace std;

class Point
{
public:
    Point(double xx, double yy)
    {
        x = xx;
        y = yy;
    }
    friend double getDistance(Point & a, Point & b);

private:
    double x, y;
};

double getDistance(Point & a, Point & b)
{
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    return sqrt(dx*dx + dy*dy);
}

int main()
{
    Point p1(1, 2);
    Point p2(3, 4);
    double dis = getDistance(p1, p2);
    cout<<dis<<endl;

    return 0;
}

Add PointManagement management class

#include <iostream>
#include <math.h>

using namespace std;

class Point;  //先声明类

class PointManagement
{
public:
    double getDirectDistance(Point & a, Point & b);  //两点间线段长度
    double getTriDistance(Point & a, Point & b);  //获得两点组成的三个边距离和
};

class Point
{
public:
    Point(double xx, double yy)
    {
        x = xx;
        y = yy;
    }
    friend double PointManagement::getDirectDistance(Point & a, Point & b);
    friend double PointManagement::getTriDistance(Point & a, Point & b);

private:
    double x, y;
};

double PointManagement::getDirectDistance(Point & a, Point & b)
{
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
}

double PointManagement::getTriDistance(Point & a, Point & b)
{
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    c1 = sqrt(dx * dx + dy * dy);
    return c1 + dx + dy;
}

int main()
{
    Point p1(1, 2);
    Point p2(3, 4);
    double dis = getDistance(p1, p2);
    cout<<dis<<endl;

    return 0;
}

Friend class: use one class as a friend of another class

By declaring A as a friend of B, you can access B's private data members through B's variables.

class Point
{
public:
    Point(double xx, double yy)
    {
        x = xx;
        y = yy;
    }
    friend class PointManagement;  //友元类

private:
    double x, y;
};

class PointManagement
{
public:
    double getDirectDistance(Point & a, Point & b);  //两点间线段长度
    double getTriDistance(Point & a, Point & b);  //获得两点组成的三个边距离和
};

Guess you like

Origin blog.csdn.net/jiangyangll/article/details/132297446