Question

I have a superclass called Animal with a method called create that does:

static Animal* Animal::create(const std::string& name)
{
Animal* newAnimal = new Animal();
newAnimal ->name = name;
return newAnimal;

}

Now I have a subclass called Dog. I want to override the create method from Animal, but avoid copy and pasting the code that is already in there... I basically want this:

static Dog* Dog::create(const std::string& name)
{
Dog* newDog = Animal::create(name); // This is the line that I have trouble with.
newDog->type="dog";
}

As I mentioned above, I noticed that C++ doesn't do automatic casting - I come from Java background...

Anyways, I was wondering if this is an acceptable way to fix it and doesn't lead to more headache:

  Dog *newDog  = static_cast<Dog *>(Animal::create(name));

ADDITIONAL NOTE: So after reading all the comments and solutions, I guess everyone suggests using constructors. But imagine a case that you are not allowed to modify the Animal class, it has a create method and you want to extend that method. Maybe a more proper way to ask is that: Is it possible to extend the super class create method? Let me know if I am totally off - I am very very very new to c++ so maybe the question is just non-sense in c++ point of view...

Was it helpful?

Solution

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 Animals are created. Here's why.

First, here's what Animal::create does.

  1. Allocates sizeof Animal bytes on heap
  2. Calls default constructor of Animal using that allocated chunk of memory.
  3. Sets the name field.
  4. Returns the pointer to the Animal object

Here is what a Dog::create function would need to do:

  1. Allocate sizeof Dog bytes on heap
  2. Initialize the Animal portion of the new Dog object. I think you are trying to reuse the Animal::create function for this?
  3. Set the type field
  4. 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.

OTHER TIPS

Usually the solution is to use constructors:

#include <string>
class animal {
public: 
    animal();
    animal(std::string name, std::string type);
    virtual ~animal();
private:
    std::string name_;
    std::string type_;
};
animal::animal() 
    :name_("unnamed"), type_("unknown") 
    {}
animal::animal(std::string name, std::string type) 
    :name_(std::move(name)), 
    type_(std::move(type)) 
    {}
animal::~animal() {}

and then:

class dog : public animal{
public: 
    dog();
    dog (std::string name);
    virtual ~dog ();
};
dog::dog() :animal("","dog") {} //delegate to the animal default constructor
dog::dog(std::string name) :animal(std::move(name), "dog") {} //delegate again
dog::~dog() {}

and that's far easier to use:

int main() {
    dog fido("fido"); //creates a dog on the stack, _very fast_
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top