virtuales puro protegidos polimorfismo herencia funciones clase atributos abstracta c++

puro - Polimorfismo en C++ sin punteros.



polimorfismo puro c++ (4)

En última instancia, no.

El polimorfismo solo funciona con tipos sin valor: referencias y punteros. Y como las referencias solo se pueden unir una vez, realmente no se pueden usar en contenedores estándar. Eso te deja con punteros.

Estás atacando el problema en el extremo equivocado. Si le preocupa la sobrecarga de asignar muchos objetos pequeños (y supongo que se trata de una preocupación legítima. Es decir, tiene datos de perfiles reales o experiencia suficiente para saber que es una preocupación para su aplicación específica ), entonces deberías arreglar eso Cambia la forma en que asignas memoria para estos objetos. Hacer un pequeño montón de asignación o algo así.

Es cierto que los asignadores de pre-C ++ 0x carecen de este aspecto, ya que tienen que ser apátridas. Pero para tus propósitos, deberías poder lidiar con eso.

Desde su edición:

Esa es una idea terrible . Borrado de un std::deque en cualquier lugar, pero el inicio o el final invalidará cada puntero en su std::list .

Dado tu comentario, esta idea es funcional. Sin embargo, tener todos estos diferentes bloques de memoria para diferentes tipos de objetos parece ir en contra de todo el punto de herencia. Después de todo, no puedes simplemente escribir un nuevo tipo de Animal y deslizarlo en la std::list ; Usted tiene que proporcionar la gestión de la memoria para ello.

¿Está seguro de que el polimorfismo basado en herencia es lo que necesita aquí? ¿Estás seguro de que alguna otra metodología no funcionaría igual de bien?

Supongamos que tengo una clase base Animal con funciones virtuales y algunas clases derivadas ( Cat , Dog , etc.). Las clases reales derivadas contienen 4-8 bytes de datos. Quiero almacenar un std::list<Animal> que en realidad contiene elementos que son objetos derivados. Quiero evitar la creación de muchos objetos pequeños en el montón utilizando nuevos.

¿Hay algún patrón de diseño que pueda usarse para lograr esto?

EDITAR: Mis ideas para implementar esto.

  1. crear std::deque<Cat> , std::deque<Dog> , ...; store std::list<Animal*> que contiene punteros de los deques ; Uso std::deque porque supongo que tiene una buena gestión de memoria con trozos de objetos;

Me doy cuenta de que esta pregunta es antigua, pero encontré una solución bastante bonita.

Suposición:

Conoces todas las clases derivadas de antemano (dada tu edición, esto es cierto).

Truco:

Usando boost :: variant ( http://www.boost.org/doc/libs/1_57_0/doc/html/variant.html )

Ejemplo de clases:

class Animal { public: virtual void eat() = 0; }; class Cat : public Animal { virtual void eat() final override { std::cout << "Mmh, tasty fish!" << std::endl; } }; class Dog: public Animal { virtual void eat() final override { std::cout << "Mmh, tasty bone!" << std::endl; } };

Variante de ejemplo / visitante:

typedef boost::variant<Cat, Dog> AnimalVariant; class AnimalVisitor : public boost::static_visitor<Animal&> { public: Animal& operator()(Cat& a) const { return a; } Animal& operator()(Dog& a) const { return a; } };

Ejemplo de uso:

std::vector<AnimalVariant> list; list.push_back(Dog()); list.emplace_back(Cat()); for(int i = 0; i < 5; i++) { for(auto& v : list) { Animal& a = v.apply_visitor(AnimalVisitor()); a.eat(); } }

Ejemplo de salida

Mmh, tasty bone! Mmh, tasty fish! Mmh, tasty bone! Mmh, tasty fish! Mmh, tasty bone! Mmh, tasty fish! Mmh, tasty bone! Mmh, tasty fish! Mmh, tasty bone! Mmh, tasty fish!


Probablemente podría hacer algo con una clase envoltura simple para una unión que contenga el conjunto de datos necesarios para cada caso. Esto contendría un puntero a objetos de strategy compartidos que contenían el código para los diferentes comportamientos. Así que un gato es un objeto de la clase PolyAnimal con speciesName = "cat", una PredatorFeedingStrategy y así sucesivamente.

Probablemente, una mejor manera de resolver el problema subyacente es configurar asignadores personalizados adecuados para un diseño más natural.


Si le preocupa asignar muchos objetos pequeños de almacenamiento dinámico, entonces un vector puede ser una mejor opción de contenedor en lugar de una lista y un deque. list asignará un nodo en el montón cada vez que inserte un objeto en la lista, mientras que vector almacenará todos los objetos en una región contigua de memoria en el montón.

Si usted tiene:

std::vector<Dog> dogs; std::vector<Cat> cats; std::vector<Animal*> animals; void addDog(Dog& dog, std::vector<Dog>& dogs, std::vector<Animal*>& animals) { dogs.push_back(dog); animals.push_back(&dog); }

Luego, todos los perros y gatos se almacenan en dos regiones contiguas de memoria en el montón.