I would just use constructors and polymorphism.
class Animal
{
const std::string name;
public:
explicit Animal(const std::string &name) : name(name) {}
virtual ~Animal() {}
virtual std::string type() const = 0;
};
class Dog : public Animal
{
public:
explicit Dog(const std::string &name) : Animal(name) {}
virtual std::string type() const { return "dog"; }
};
If you really don't like the polymorphism for whatever reason, then add a type
data member in Animal
, and assign to it in the Dog::Dog
(Dog constructor).
I don't think you can do what you are trying to do without changing how Animal
s are created. Here's why.
First, here's what Animal::create
does.
- Allocates
sizeof Animal
bytes on heap - Calls default constructor of
Animal
using that allocated chunk of memory. - Sets the
name
field. - Returns the pointer to the
Animal
object
Here is what a Dog::create
function would need to do:
- Allocate
sizeof Dog
bytes on heap - Initialize the
Animal
portion of the newDog
object. I think you are trying to reuse theAnimal::create
function for this? - Set the
type
field - Return the pointer to the
Dog
object
The problem is with step 2 of Dog::create
. Since Animal::create
allocates its own memory and you can't pass in a pointer to a Dog
, there is no way to get Animal::create
to operate on the memory you allocated in step 1.
That said, depending on the internals of Animal
and specifically if it is copyable, you may be able to hack it as follows, but I'm not sure it would work or even be well-defined
static Dog * Dog::create(static Dog* Dog::create(const std::string& name)
{
Animal *animalTmp = Animal::create(name);
Dog* newDog = new Dog(); // note that Animal::Animal() c-tor is probably called
*newDog = *animalTmp; // you have to be careful about which `operator=` is called here
delete animalTmp;
newDog->type="dog";
return newDog;
}
This is completely unmaintainable, ugly as hell, very brittle, and A TERRIBLE IDEA.