Introduction to C++ (2) First Classes and Objects

One, the introduction of the class

In the C language, only variables are allowed to be defined in the structure body, and functions are not allowed to be defined.
In C++, not only variables can be defined in the structure, but also functions can be defined.
Take the sequence table we created manually as an example:
when C language was implemented in the past, a structure was defined to store data, and some global functions were provided to process data.
In C++, both data and data processing methods (ie functions) are placed in the interior of the structure.

struct SeqList
{
    
    
    void init(int n = 4)
    {
    
    
        _a = (int*)malloc(sizeof(int) * n);
        if (_a == nullptr)
        {
    
    
            perror("malloc fail");
            exit(-1);
        }
        _size = 0;
        _capcity = n;
    }
    void Destroy()
    {
    
    
        if (_a)
        {
    
    
            free(_a);
            _a = nullptr;
            _size = _capcity = 0;
        }
    }
    void Push_Back(int x)
    {
    
    
        if (_size == _capcity)
        {
    
    
            // ...
        }
        _a[_size++] = x;
    }
    int* _a;
    int _size;
    int _capcity;
};

int main()
{
    
    
    SeqList L1;
    L1.init();
    L1.Push_Back(1);
    L1.Push_Back(2);
    L1.Push_Back(3);
    L1.Destroy();
    return 0;
}

Compared with the C language implementation, C++ is simplified a bit.
The global function defined by C language is generally famous for the function about the sequence table: SeqListInit.
When calling related functions in C language, a pointer variable of the sequence table structure must be passed.

Second, the definition of the class

In C++, the struct keyword is generally not used to define a class, but the class keyword is used to define a class.
Variables in a class are called member variables.
Functions in a class are called member functions.

class classname
{
    
    
    // 成员函数 ...

    // 成员变量 ...
};

Two ways to define member functions

  • Declare and define
    functions within a class. It should be noted that the compiler may treat them as inline functions.
  • In-class declarations and out-of-class definitions
    generally define the class in the header file and define member functions in the source file. It should be noted that because the class determines a new scope, the member function is in this role of the class. Under the domain, so when defining a member function outside the class, an access qualifier must be added.
class SeqList
{
    
    
    void init(int n = 4);
    void Destroy();
	void Push_Back(int x);
    int* _a;
    int _size;
    int _capcity;
};

void SeqList::init(int n = 4)
{
    
    
    _a = (int*)malloc(sizeof(int) * n);
    if (_a == nullptr)
    {
    
    
        perror("malloc fail");
        exit(-1);
    }
    _size = 0;
    _capcity = n;
}
void SeqList::Destroy()
{
    
    
    if (_a)
    {
    
    
        free(_a);
        _a = nullptr;
        _size = _capcity = 0;
    }
}
void SeqList::Push_Back(int x)
{
    
    
    if (_size == _capcity)
    {
    
    
        // ...
    }
    _a[_size++] = x;
}

Third, the class access qualifier

There are three types of access qualifiers for classes in C++

public
Members modified by public allow direct access outside the class
private
Members modified by private are not allowed to be directly accessed outside the class
protected
Members modified by protected are not allowed to be directly accessed outside the class

Notice

  • The scope of access rights starts from the position where the access qualifier appears until the next access qualifier appears. If there are no more access qualifiers, the scope ends at the end of the class.
  • The default access permission of class is private, and the default access permission of struct is public.
  • Access qualifiers are only useful at compile time, when the data is mapped to memory, there is no difference in access qualifiers.

Fourth, the scope of the class

A class defines a new scope, and all members of the class are in the scope of the class. When defining members outside the class, you need to use the :: scope operator to indicate which class domain the member belongs to.

class SeqList
{
    
    
public:
    void init(int n = 4);
    void Destroy();
	void Push_Back(int x);
private:
    int* _a;
    int _size;
    int _capcity;
};

void SeqList::init(int n = 4)
{
    
    
    _a = (int*)malloc(sizeof(int) * n);
    if (_a == nullptr)
    {
    
    
        perror("malloc fail");
        exit(-1);
    }
    _size = 0;
    _capcity = n;
}
void SeqList::Destroy()
{
    
    
    if (_a)
    {
    
    
        free(_a);
        _a = nullptr;
        _size = _capcity = 0;
    }
}
void SeqList::Push_Back(int x)
{
    
    
    if (_size == _capcity)
    {
    
    
        // ...
    }
    _a[_size++] = x;
}

Five, class instantiation

  • The declaration of a class describes the object, which is like a model, which defines which members the class has, and defines a class without allocating actual memory space to store it.
  • A class can instantiate multiple objects, and the instantiated objects occupy physical space.
  • The declaration of a class is like a blueprint for building a house, and the instantiated objects are houses.

Six, the calculation of the object size of the class

  • First of all, the classMember variables are stored on the class,andMember functions are not stored on the class, but exists on the snippet. (Because even if the data of their member variables may be different for different objects, the member functions they call are all the same. If the member functions store a copy in each object, it would be a waste of space)
  • The alignment of the member variables of the class is the same as the alignment of the struct structure in the C language
    Structure Alignment
    1, 1. The first member is at the offset 0 relative to the address of the structure variable.
    2. Other member variables should be aligned to an address that is an integer multiple of the alignment number.
    Note: Alignment = the smaller value between the compiler's default alignment and the member size.
    The default alignment number in VS is 8
    3, and the total size of the structure is an integer multiple of the maximum alignment number (the largest among all member alignment numbers).
    4. If a structure is nested, the nested structure is aligned to an integer multiple of its maximum alignment number, and the overall size of the structure is the integer of all maximum alignment numbers (including the alignment number of the nested structure) times
    Notice
  • The size of an object instantiated from an empty class is one byte, which is used by the compiler to identify the object.

Seven, the this pointer of the class member function

Have you ever noticed a problem:
a class instantiates multiple objects, and when these multiple objects call the same member function, the address of the object is obviously not passed, how does the member function distinguish which object is calling it? Woolen cloth?

that's because there arethis pointerThe presence.
The C++ compiler adds ahidden pointer parameter, let the pointer point to the current object (the object that calls the function when the function is running), and all operations of "member variables" in the function body are accessed through the pointer. It's just that all operations are transparent to the user, that is, the user does not need to pass it, and the compiler completes it automatically.

  • Characteristics of this pointer
  1. The type of this pointer: class type * const, that is, in member functions, the this pointer cannot be assigned a value.
  2. Can only be used inside a "member function"
  3. The this pointer is essentially a formal parameter of a "member function". When an object calls a member function, the object address is passed as an actual parameter to this formal parameter. Therefore, the this pointer is not stored in the object, and the this pointer exists on the stack frame of the member function.
  4. The this pointer is the first implicit pointer parameter of the "member function", generally passed by the compilerecx registerPassed automatically
    , no user pass required
  • two classic questions
// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
    
    
public:
    void Print()
    {
    
    
        cout << "Print()" << endl;
    }
private:
    int _a;
};
int main()
{
    
    
    A* p = nullptr;
    p->Print();
    return 0;
}

Many beginners will think that this program will crash properly due to the dereferencing of the null pointer.
However, the answer is not like this.
insert image description here

Since the member function Print is not stored on an instantiated object, the p pointer does not need to dereference the pointer of the object to get the object if it wants to call the function, and then call the function in the object.

class A
{
    
    
public:
    void PrintA()
    {
    
    
        cout << _a << endl;
    }
private:
    int _a;
};
int main()
{
    
    
    A* p = nullptr;
    p->PrintA();
    return 0;
}

This program will crash properly. Since the member variable _a is accessed in the PrintA function, although the member function is not stored on the object, the member variable is stored on the object. If you want to access _a, you need to refer to the pointer dereference.

Summarize

Even if a pointer variable p points to nullptr, p->..., or *p... does not necessarily cause dereferencing a null pointer, but depends on its specific function.

Guess you like

Origin blog.csdn.net/Djsnxbjans/article/details/128924799