Introducción a C++ (2) Primeras Clases y Objetos

Uno, la introducción de la clase.

En el lenguaje C, solo se permite definir variables en el cuerpo de la estructura y no se permite definir funciones.
En C++, no solo se pueden definir variables en la estructura, sino que también se pueden definir funciones.
Tome la tabla de secuencia que creamos manualmente como ejemplo:
cuando se implementó el lenguaje C en el pasado, se definió una estructura para almacenar datos y se proporcionaron algunas funciones globales para procesar datos.
En C++, tanto los datos como los métodos de procesamiento de datos (es decir, funciones ) se colocan en el interior de la estructura.

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;
}

En comparación con la implementación del lenguaje C, C++ se simplifica un poco.
La función global definida por el lenguaje C es generalmente famosa por la función sobre la tabla de secuencias: SeqListInit.
Al llamar a funciones relacionadas en lenguaje C, se debe pasar una variable de puntero de la estructura de la tabla de secuencia.

En segundo lugar, la definición de la clase.

En C++, la palabra clave struct generalmente no se usa para definir una clase, pero la palabra clave class se usa para definir una clase.
Las variables de una clase se denominan variables miembro.
Las funciones de una clase se denominan funciones miembro.

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

    // 成员变量 ...
};

Dos formas de definir funciones miembro

  • Declarar y definir
    funciones dentro de una clase Cabe señalar que el compilador puede tratarlas como funciones en línea.
  • Las declaraciones dentro de la clase y las definiciones fuera de la clase
    generalmente definen la clase en el archivo de encabezado y definen las funciones miembro en el archivo fuente. Cabe señalar que debido a que la clase determina un nuevo alcance, la función miembro tiene este rol del clase Bajo el dominio, por lo que al definir una función miembro fuera de la clase, se debe agregar un calificador de acceso.
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;
}

Tercero, el calificador de acceso a la clase.

Hay tres tipos de calificadores de acceso para clases en C++

público
Los miembros modificados por público permiten el acceso directo fuera de la clase
privado
No se permite acceder directamente a los miembros modificados por privado fuera de la clase
protegido
No se permite acceder directamente a los miembros modificados por protected fuera de la clase

Aviso

  • El alcance de los derechos de acceso comienza desde la posición donde aparece el calificador de acceso hasta que aparece el siguiente calificador de acceso, si no hay más calificadores de acceso, el alcance finaliza al final de la clase.
  • El permiso de acceso predeterminado de la clase es privado y el permiso de acceso predeterminado de la estructura es público.
  • Los calificadores de acceso solo son útiles en tiempo de compilación, cuando los datos se asignan a la memoria, no hay diferencia en los calificadores de acceso.

Cuarto, el alcance de la clase.

Una clase define un nuevo ámbito y todos los miembros de la clase están en el ámbito de la clase. Al definir miembros fuera de la clase, debe usar el operador de ámbito :: para indicar a qué dominio de clase pertenece el miembro.

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;
}

Cinco, creación de instancias de clase

  • La declaración de una clase describe el objeto, que es como un modelo, que define qué miembros tiene la clase y define una clase sin asignar espacio de memoria real para almacenarla.
  • Una clase puede instanciar múltiples objetos y los objetos instanciados ocupan espacio físico.
  • La declaración de una clase es como un plano para construir una casa, y los objetos instanciados son casas.

Seis, el cálculo del tamaño del objeto de la clase.

  • En primer lugar, la clase.Las variables miembro se almacenan en la clase.,yLas funciones miembro no se almacenan en la clase., pero existe en el fragmento. (Porque incluso si los datos de sus variables miembro pueden ser diferentes para diferentes objetos, las funciones miembro a las que llaman son todas iguales. Si las funciones miembro almacenan una copia en cada objeto, sería una pérdida de espacio)
  • La alineación de las variables miembro de la clase es la misma que la alineación de la estructura struct en el lenguaje C
    Alineación de estructuras
    1, 1. El primer miembro está en el desplazamiento 0 relativo a la dirección de la variable de estructura.
    2. Otras variables miembro deben alinearse con una dirección que sea un múltiplo entero del número de alineación.
    Nota: Alineación = el valor más pequeño entre la alineación predeterminada del compilador y el tamaño del miembro.
    El número de alineación predeterminado en VS es 8
    3, y el tamaño total de la estructura es un múltiplo entero del número máximo de alineación (el más grande entre todos los números de alineación de miembros).
    4. Si una estructura está anidada, la estructura anidada se alinea con un múltiplo entero de su número máximo de alineación, y el tamaño total de la estructura es el número entero de todos los números máximos de alineación (incluido el número de alineación de la estructura anidada) veces
    Aviso
  • El tamaño de un objeto instanciado desde una clase vacía es de un byte, que el compilador utiliza para identificar el objeto.

Siete, el puntero this de la función miembro de clase

¿Alguna vez ha notado un problema:
una clase instancia múltiples objetos, y cuando estos múltiples objetos llaman a la misma función miembro, la dirección del objeto obviamente no se pasa, ¿cómo distingue la función miembro qué objeto lo está llamando?¿Paño de lana?

eso es porque hayeste punteroLa presencia.
El compilador de C++ agrega unparámetro de puntero oculto, deje que el puntero apunte al objeto actual (el objeto que llama a la función cuando la función se está ejecutando), y se accede a todas las operaciones de "variables miembro" en el cuerpo de la función a través del puntero. Es solo que todas las operaciones son transparentes para el usuario, es decir, el usuario no necesita pasarlo y el compilador lo completa automáticamente.

  • Características de este puntero
  1. El tipo de este puntero: tipo de clase * const, es decir, en las funciones miembro, al puntero this no se le puede asignar un valor.
  2. Solo se puede usar dentro de una "función miembro"
  3. El puntero this es esencialmente un parámetro formal de una "función miembro". Cuando un objeto llama a una función miembro, la dirección del objeto se pasa como un parámetro real a este parámetro formal. Por lo tanto, el puntero this no se almacena en el objeto y existe en el marco de pila de la función miembro.
  4. El puntero this es el primer parámetro de puntero implícito de la "función miembro", generalmente pasado por el compiladorregistro ecxAprobado automáticamente
    , no se requiere pase de usuario
  • dos preguntas clasicas
// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
    
    
public:
    void Print()
    {
    
    
        cout << "Print()" << endl;
    }
private:
    int _a;
};
int main()
{
    
    
    A* p = nullptr;
    p->Print();
    return 0;
}

Muchos principiantes pensarán que este programa fallará correctamente debido a la desreferenciación del puntero nulo.
Sin embargo, la respuesta no es así.
inserte la descripción de la imagen aquí

Dado que la función miembro Print no se almacena en un objeto instanciado, el puntero p no necesita eliminar la referencia del puntero del objeto para obtener el objeto si desea llamar a la función y luego llamar a la función en el objeto.

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

Este programa fallará correctamente. Dado que se accede a la variable miembro _a en la función PrintA, aunque la función miembro no está almacenada en el objeto, la variable miembro está almacenada en el objeto. Si desea acceder a _a, debe consultar la desreferencia del puntero.

Resumir

Incluso si una variable de puntero p apunta a nullptr, p->... o *p... no provoca necesariamente la desreferenciación de un puntero nulo, sino que depende de su función específica.

Supongo que te gusta

Origin blog.csdn.net/Djsnxbjans/article/details/128924799
Recomendado
Clasificación