suaje recorte quitar marcas marca lineas las illustrator hacer guias demasia cs6 corte como colocar c++ arrays inheritance terminology pointer-arithmetic

c++ - recorte - ¿Debería llamarse este caso especial de corte de objetos?



marcas de suaje en illustrator (4)

Esto no es rebanar objetos.

Como se señaló, la indexación de myArray no causa la myArray objetos, pero produce un comportamiento indefinido causado por la indexación en una matriz de Derived como si fuera una matriz de Base .

Una especie de "error de desintegración de la matriz".

El error introducido en la asignación de new Derived[42] a myArray puede ser una variación de un error de desintegración de matriz .

En una verdadera instancia de este tipo de error, hay una matriz real:

Derived x[42]; Base *myArray = x;

El problema se presenta porque una matriz de Derived desintegra en un puntero a Derived con un valor igual a la dirección de su primer elemento. El decaimiento permite que la asignación del puntero funcione correctamente. Este comportamiento de decaimiento se hereda de C, que era una característica de diseño de lenguaje para permitir que las matrices se "pasen por referencia".

Esto nos lleva a la encarnación aún peor de este error. Esta característica proporciona semántica de C y C ++ para la sintaxis de matrices que convierten los argumentos de la función de matriz en alias para los argumentos de puntero.

void foo (Base base_array[42]) { //... } Derived d[42]; foo(d); // Boom.

Sin embargo, new[] es en realidad un operador sobrecargado que devuelve un puntero al principio del objeto de matriz asignado. Por lo tanto, no es una verdadera instancia de la desintegración de la matriz (aunque se use el asignador de matriz). Sin embargo, los síntomas de error son los mismos, y la intención de new[] es obtener una matriz de Derived .

Detectando y evitando el error.

Utilice un puntero inteligente.

Este tipo de problema se puede evitar mediante el uso de un puntero inteligente en lugar de administrar un puntero en bruto. Por ejemplo, el error de codificación análoga con unique_ptr se vería así:

std::unique_ptr<Base[]> myArray = new Derived[42];

Esto generaría un error de tiempo de compilación, porque el constructor de unique_ptr es explicit

Use un contenedor, y tal vez std::reference .

Alternativamente, podría evitar usar el new[] y usar std::vector<Derived> . Entonces, se habría forzado a diseñar una solución diferente para enviar esta matriz al código de marco que solo es compatible con Base . Posiblemente, una función de plantilla.

void my_framework_code (Base &object) { //... } template <typename DERIVED> void my_interface(std::vector<DERIVED> &v) { for (...) { my_framework_code(v[i]); } }

O, usando std::reference_wrapper<Base> .

std::vector<Derived> v(42); std::vector<std::reference_wrapper<Base>> myArray(v.begin(), v.end());

Digamos que tengo una clase Derived que deriva de la clase Base mientras que sizeof(Derived) > sizeof(Base) . Ahora, si uno asigna una matriz de Derived como este:

Base * myArray = new Derived[42];

y luego intenta acceder al n -ésimo objeto usando

doSomethingWithBase(myArray[n]);

Entonces es probable que esto (pero no siempre) cause un comportamiento indefinido debido al acceso a la Base desde una ubicación no válida.

¿Cuál es el término correcto para tal error de programación? ¿Debería considerarse un caso de corte de objetos ?


Este no es un caso de rebanar, aunque es muy similar. El rebanado está bien definido. Esto es simplemente un comportamiento indefinido (siempre, no solo probable) debido a la aritmética de punteros ilegal.


Esto no es rebanar objetos de ninguna manera.

La división de objetos está perfectamente definida por el estándar C ++. Puede ser una violación de los principios de diseño orientados a objetos o lo que sea, pero no es una violación de las reglas de C ++.

Este código viola el párrafo 7 [expr.add] 5.7 :

Para la suma o la resta, si las expresiones P o Q tienen el tipo "puntero a cv T ", donde T es diferente del tipo de elemento de matriz no calificado cv, el comportamiento es indefinido. [Nota: en particular, un puntero a una clase base no se puede usar para la aritmética de punteros cuando la matriz contiene objetos de un tipo de clase derivado. —Endente final].

El operador de subíndice de matriz se define como equivalente a aritmética de punteros, 5.2.1 [expr.sub] párrafo 1 :

La expresión E1[E2] es idéntica (por definición) a *((E1)+(E2))


No se corta en absoluto, más bien es un comportamiento indefinido porque está accediendo a un objeto Derived donde no existe ninguno (a menos que tenga suerte y los tamaños estén alineados, en cuyo caso aún es UB pero podría hacer algo útil de todos modos).

Es un caso simple de aritmética de punteros fallidos.