C++ Modificadores de acceso de clases

C++ 类 & 对象Clases y objetos en C++

En la programación orientada a objetos (OOP) de C++, la encapsulación de datos (Encapsulation) es uno de los conceptos centrales. En pocas palabras, consiste en "ocultar" los datos y solo exponer las interfaces necesarias para uso externo, con el fin de garantizar la seguridad de los datos.

Para controlar quién puede ver estos datos, C++ proporciona tres palabras clave, llamadasmodificadores de acceso:

  • public(público)
  • private(privado)
  • protected(protegido)
class Base { public: // miembro público protected: // miembro protegido private: // miembro privado };

Para facilitar la comprensión, podemosimaginar una clase (Class) como tu casa.:

modificador Analogía en la vida real ¿Quién puede acceder? Uso típico
public Sala de estar / puerta principal Todos(interno de la clase, subclases, código externo) Funciones de interfaz (API) proporcionadas al exterior.
protected Dormitorio Tú y tus hijos(interno de la clase, subclases) Datos utilizados únicamente dentro de la familia (jerarquía de herencia).
private Caja fuerte Solo tú mismo(solo dentro de la propia clase) Datos centrales, variables que no se desea que se modifiquen arbitrariamente.

Nota: si no se escribe ningún modificador, los miembros de la clase C++por defecto sonprivate(privados).

Miembros públicos (public)

públicoLos miembros se pueden acceder desde cualquier parte del programa, sin necesidad de leerlos o escribirlos mediante funciones miembro. Ejemplo:

Ejemplo

#include <iostream> using namespace std; class Line { public: double length; void setLength( double len ); double getLength( void ); }; // definición de la función miembro double Line::getLength(void) { return length ; } void Line::setLength( double len ) { length = len; } // función principal del programa int main( ) { Line line; // establece la longitud line.setLength(6.0); cout << "Length of line : " << line.getLength() <<endl; // establece la longitud sin usar una función miembro line.length = 10.0; // OK: porque length es público cout << "Length of line : " << line.length <<endl; return 0; }

Cuando el código anterior se compila y se ejecuta, produce los siguientes resultados:

Length of line : 6
Length of line : 10

Miembros privados (private)

Los miembros privados están completamente cerrados fuera de la clase; el código externo no puede leerlos, modificarlos ni invocarlos, y las clases derivadas tampoco tienen derecho a acceder directamente a ellos. Solo las funciones miembro de la propia clase y las entidades a las que se les haya otorgado permiso de amistad (friend) pueden operar sobre estos contenidos.

Si en la clase no se utiliza ningún especificador de acceso, los miembros son privados por defecto. Como se muestra en el siguiente ejemplo, width cae automáticamente en la zona privada, lo que indica que todos los miembros no marcados explícitamente se tratan como privados:

Ejemplo

class Box { double width; public: double length; void setWidth( double wid ); double getWidth( void ); };

En la práctica, generalmente definimos los datos en la zona privada y las funciones relacionadas en la zona pública, para que estas funciones también puedan ser invocadas desde fuera de la clase, como se muestra a continuación:

Ejemplo

#include <iostream> using namespace std; class Box { public: double length; void setWidth( double wid ); double getWidth( void ); private: double width; }; // definición de la función miembro double Box::getWidth(void) { return width ; } void Box::setWidth( double wid ) { width = wid; } // función principal del programa int main( ) { Box box; // establece la longitud sin usar una función miembro box.length = 10.0; // OK: porque length es público cout << "Length of box : " << box.length <<endl; // establece el ancho sin usar una función miembro // box.width = 10.0; // Error: porque width es privado box.setWidth(10.0); // establece el ancho usando una función miembro cout << "Width of box : " << box.getWidth() <<endl; return 0; }

Cuando el código anterior se compila y se ejecuta, produce los siguientes resultados:

Length of box : 10
Width of box : 10

Miembros protegidos (protected)

protectedLa existencia de estos es principalmente parala herencia。

  • Si no hay herencia, esprivateigual (invisible para los externos).
  • Si hay herencia,las subclases (clases derivadas) pueden acceder a losprotectedmiembros, pero no pueden acceder a losprivatemiembros.

En el próximo capítulo, aprenderá sobre clases derivadas y herencia. Ahora puede ver en el siguiente ejemplo que de la clase baseBoxderivamos una subclasesmallBox。

El siguiente ejemplo es similar al anterior; aquíwidthel miembro puede ser accedido por cualquier función miembro de la clase derivada smallBox.

Ejemplo

#include <iostream> using namespace std; class Box { protected: double width; }; class SmallBox:Box // SmallBox es la clase derivada { public: void setSmallWidth( double wid ); double getSmallWidth( void ); }; // función miembro de la subclase double SmallBox::getSmallWidth(void) { return width ; } void SmallBox::setSmallWidth( double wid ) { width = wid; } // función principal del programa int main( ) { SmallBox box; // establece el ancho usando una función miembro box.setSmallWidth(5.0); cout << "Width of box : "<< box.getSmallWidth() << endl; return 0; }

Cuando el código anterior se compila y se ejecuta, produce los siguientes resultados:

Width of box : 5

Cambios de acceso en la herencia

Cuando define una subclase (por ejemplo,class B : public A), lo que sigue a los dos puntospublictambién es un modificador de acceso, que determinacómo se "comportan" los miembros de la clase padre en la subclase.。

Esto parece complicado, pero solo tiene que recordar esteprincipio de degradación:

La forma de herencia determina el permiso máximo de los miembros de la clase padre en la subclase.
Si la forma de herencia es más estricta que el permiso original del miembro, el permiso del miembro se "degrada" al nivel de la forma de herencia.

Tabla de cambios de permisos

Permiso original del miembro de la clase padre Herencia public(la más común) Herencia protected Herencia private
public Se mantiene public Se degrada a protected Se degrada a private
protected Se mantiene protected Se mantiene protected Se degrada a private
private Inaccesible Inaccesible Inaccesible

Nota: inaccesible significa que el código de la subclase no puede usar directamente esa variable, pero la variable todavía existe en la memoria.

Código de demostración completo

Para mostrar claramente, renombramos las variables comopub_var(público),pro_var(protegido),pri_var(privado).

Ejemplo

#include <iostream>
using namespace std;

class Parent {
public:
    int pub_var;
protected:
    int pro_var;
private:
    int pri_var; // Solo Parent mismo puede acceder

public:
    Parent() { pub_var = 1; pro_var = 2; pri_var = 3; }
};

// 1. Herencia pública (Public Inheritance) - la más común, tal cual
class ChildA : public Parent {
public:
    void test() {
        cout << pub_var << endl; // OK
        cout << pro_var << endl; // OK
        // cout << pri_var << endl; // ¡Error! Los miembros privados de la clase padre no son visibles
    }
};

// 2. Herencia protegida (Protected Inheritance) - todos se vuelven protegidos
class ChildB : protected Parent {
public:
    void test() {
        cout << pub_var << endl; // OK, pero desde la perspectiva de ChildB, es protected
        cout << pro_var << endl; // OK
    }
};

// 3. Herencia privada (Private Inheritance) - todos se vuelven privados
class ChildC : private Parent {
public:
    void test() {
        cout << pub_var << endl; // OK, pero desde la perspectiva de ChildC, es private
        cout << pro_var << endl; // OK, pero desde la perspectiva de ChildC, es private
    }
};

int main() {
    ChildA a;
    cout << a.pub_var << endl; // OK, el exterior puede acceder
    // cout << a.pro_var << endl; // Error, el exterior no puede acceder a protected

    ChildB b;
    // cout << b.pub_var << endl; // ¡Error! Porque es herencia protected, pub_var se vuelve protected fuera

    ChildC c;
    // cout << c.pub_var << endl; // ¡Error! Porque es herencia private, pub_var se vuelve private fuera

    return 0;
}

Resumen

  • Public: Todo el mundo puede usarlo. Se usa como interfaz (API).
  • Private: Solo uno mismo puede usarlo. Para almacenar datos (opción segura por defecto).
  • Protected: Solo la familia (cadena de herencia) puede usarlo. Para dejar una puerta trasera a las subclases.

Herencia:

  • Herencia Public: los atributos de la clase padre permanecen sin cambios (la más común).
  • Herencia Private/Protected: restringirá los permisos de los miembros de la clase padre, generalmente se usa en escenarios de implementación especiales.

C++ 类 & 对象Clases y objetos en C++

Otras extensiones