Esto es lo que quiero decir:
class MyClass {
int arr1[100];
int arr2[100];
int len = 100;
void add(int* x1, int* x2, int size) {
for (int i = 0; i < size; i++) {
x1[i] += x2[i];
}
}
};
int main() {
MyClass myInstance;
// Fill the arrays...
myInstance.add(myInstance.arr1, myInstance.arr2, myInstance.len);
}
add
ya puede acceder a todas las variables que necesita, ya que es un método de clase, ¿es una mala idea? ¿Hay razones por las que debería o no debería hacer esto?
object-oriented
c++
class-design
methods
encapsulation
hombre de papel
fuente
fuente
add
método sin argumentos que opera directamente en sus componentes internos? ¿Solo porque?add
método que toma argumentos pero no existe como parte de una clase. Solo una función pura para agregar dos matrices juntas.Respuestas:
Hay muchas cosas con la clase que haría de manera diferente, pero para responder la pregunta directa, mi respuesta sería
si, es una mala idea
Mi razón principal para esto es que no tienes control sobre lo que se pasa a la
add
función. Seguro que espera que sea una de las matrices de miembros, pero ¿qué sucede si alguien pasa en una matriz diferente que tiene un tamaño menor a 100, o usted pasa en una longitud mayor a 100?Lo que sucede es que ha creado la posibilidad de un desbordamiento del búfer. Y eso es algo malo por todas partes.
Para responder algunas preguntas más obvias (para mí):
Está mezclando matrices de estilo C con C ++. No soy un gurú de C ++, pero sí sé que C ++ tiene formas mejores (más seguras) de manejar matrices
Si la clase ya tiene las variables miembro, ¿por qué necesita pasarlas? Esto es más una cuestión arquitectónica.
Otras personas con más experiencia en C ++ (dejé de usarlo hace 10 o 15 años) pueden tener formas más elocuentes de explicar los problemas, y probablemente también tengan más problemas.
fuente
vector<int>
sería más adecuado; la longitud sería inútil. Alternativamenteconst int len
, dado que la matriz de longitud variable no es parte del estándar C ++ (aunque algunos compiladores lo admiten, porque es una característica opcional en C).std::array
que no se descompone al pasarla a los parámetros, tiene una forma más conveniente de obtener su tamaño, es copiable y tiene acceso con verificación de límites opcional, sin tener sobrecarga Matrices de estilo C.Llamar a un método de clase con algunas variables de clase no es necesariamente malo. Pero hacerlo desde fuera de la clase es una muy mala idea y sugiere una falla fundamental en su diseño OO, a saber, la ausencia de una encapsulación adecuada :
len
es la longitud de la matriz, y usarlo consistentemente. Esto va en contra del principio del mínimo conocimiento . Dicha dependencia de los detalles internos de la clase es extremadamente propensa a errores y arriesgada.len
a una más modernastd::vector<int>
), ya que requeriría que también cambie todo el código usando su clase.MyClass
objetos al corromper algunas variables públicas sin respetar las reglas (llamadas invariantes de clase )Debe refactorizar su código y:
private
oprotected
, a menos que haya una buena razón para no hacerlo.object.action(additional parameters for the action)
.fuente
Cuando la intención de este diseño es que desea poder reutilizar este método para datos que no provienen de esta instancia de clase, es posible que desee declararlo como un
static
método .Un método estático no pertenece a ninguna instancia particular de una clase. Es más bien un método de la clase misma. Debido a que los métodos estáticos no se ejecutan en el contexto de ninguna instancia particular de la clase, solo pueden acceder a las variables miembro que también se declaran como estáticas. Teniendo en cuenta que su método
add
no hace referencia a ninguna de las variables miembro declaradas enMyClass
, es un buen candidato para ser declarado como estático.Sin embargo, los problemas de seguridad mencionados por las otras respuestas son válidos: no está comprobando si ambas matrices son al menos
len
largas. Si desea escribir C ++ moderno y robusto, debe evitar el uso de matrices. Utilice la clase en sustd::vector
lugar siempre que sea posible. Contrariamente a las matrices regulares, los vectores conocen su propio tamaño. Por lo tanto, no necesita hacer un seguimiento de su tamaño. La mayoría (¡no todos!) De sus métodos también realizan comprobaciones de límite automáticas, lo que garantiza que obtendrá una excepción cuando lea o escriba más allá del final. El acceso regular a la matriz no realiza la comprobación de límites, lo que resulta en un defecto de seguridad en el mejor de los casos y puede causar una vulnerabilidad de desbordamiento de búfer explotable en el peor de los casos .fuente
Un método en una clase idealmente manipula datos encapsulados dentro de la clase. En su ejemplo, no hay ninguna razón para que el método add tenga parámetros, simplemente use las propiedades de la clase.
fuente
Pasar (parte de) un objeto a una función miembro está bien. Al implementar sus funciones, siempre debe ser consciente de posibles alias y sus consecuencias.
Por supuesto, el contrato puede dejar algunos tipos de alias indefinidos incluso si el idioma lo admite.
Ejemplos destacados:
La asignación de auto-movimiento, por otro lado, aunque no debería explotar en tu cara, no tiene por qué ser un no-op.
v.push_back(v[2]);
.std::copy()
asume que el destino no comienza dentro de la fuente.Pero tu ejemplo tiene diferentes problemas:
this
. Actúa como una función de utilidad gratuita que simplemente está en el lugar equivocado.En resumen: sí, este ejemplo es malo. Pero no porque la función miembro pase objetos miembro.
fuente
Hacer esto específicamente es una mala idea por varias buenas razones, pero no estoy seguro de que todas sean parte integral de su pregunta:
vector<int>
Haría tu vida más fácil.fuente
Este es un enfoque clásico de "C con clases" para C ++. En realidad, esto no es lo que escribiría cualquier programador experimentado de C ++. Por un lado, el uso de matrices C sin procesar es bastante universalmente desaconsejado, a menos que esté implementando una biblioteca de contenedores.
Algo como esto sería más apropiado:
fuente