En el siguiente código:¿Es peligroso ampliar una clase base con un destructor no virtual?
class A {
};
class B : public A {
};
class C : public A {
int x;
};
int main (int argc, char** argv) {
A* b = new B();
A* c = new C();
//in both cases, only ~A() is called, not ~B() or ~C()
delete b; //is this ok?
delete c; //does this line leak memory?
return 0;
}
Cuando se llama a borrar en una clase con un destructor no virtual con funciones miembro (como la clase C), puede el asignador de memoria diga qué el tamaño apropiado del objeto es? Si no, ¿se ha filtrado la memoria?
En segundo lugar, si la clase no tiene funciones de miembro, y no hay un comportamiento de destructor explícito (como la clase B), ¿está todo bien?
Lo pregunto porque quería crear una clase para extender std::string
, (que sé que no es recomendable, pero en aras de la discusión acaba de llevar con él), y la sobrecarga del operador +=
, +
. -WeffC++ me da una advertencia porque std::string
tiene un destructor no virtual, pero ¿Importa si la subclase no tiene miembros y no necesita hacer nada en su destructor?
FYI la sobrecarga +=
era hacer el formato de ruta de archivo adecuado, por lo que la clase de ruta podría ser utilizado como:
class path : public std::string {
//... overload, +=, +
//... add last_path_component, remove_path_component, ext, etc...
};
path foo = "/some/file/path";
foo = foo + "filename.txt";
std::string s = foo; //easy assignment to std::string
some_function_taking_std_string (foo); //easy implicit conversion
//and so on...
solo quería asegurarse de que alguien hacer esto:
path* foo = new path();
std::string* bar = foo;
delete bar;
sería no causa ningún problema con la asignación de memoria?
Ambos ejemplos no protegen a nadie de eliminar a través del puntero base, obteniendo un comportamiento indefinido. Para el primero, es mejor tener un contenedor privado y un operador de conversión. Para el segundo, una estructura con un typedef dentro de los servidores tiene el mismo propósito. – GManNickG
@GMan Estoy de acuerdo en que la eliminación sería mala, y específicamente digo que no debes usar estos objetos con asignaciones nuevas. Si estás eliminando algo que no fue renovado, te topas con UB sin importar nada. También sugiero cómo evitar la convocatoria de nuevos ... pero yo mismo no lo he intentado. –
@GMan también, encuentro "CustomAllocMap :: type map_" un poco menos intuitivo de leer que "CustomAllocMap map_" ... pero el typedef en una estructura con plantilla es una buena opción. –