I have one class called Animal
class Animal
{
std::string name;
public:
Animal(string n)
{
name = n;
}
string getname()
{
return name;
}
};
and two inherited classes Cat and Dog
class Cat : public Animal
{
public:
Cat(string name):Animal(name)
{}
};
class Dog : public Animal
{
public:
Dog(string name):Animal(name){}
};
and i have a class called AnimalQueue which contains 2 lists, cat list and dog list
class AnimalQueue
{
std::list<Cat*> cats;
std::list<Dog*> dogs;
public:
void Enqueue(Animal a)
{
if(a.getname().compare("Cat") == 0)
{
// what should i do here
}
else
{
// what should i do here
}
}
};
what i want it, when i enter cat then it should go to the cat list and same with dog also in Enqueue function. I am not sure how it would work, how can i type cast from Animal to Cat or to Dog.
I tried
Cat *c = (Cat*) &a;
but it dows not work.
int main()
{
string name = "Cat";
Cat c(name);
name = "Dog";
Dog d(name);
AnimalQueue aq;
aq.Enqueue(c);
aq.Enqueue(d);
}
This is working code, you can copy paste in your editor. you can change the signature of Animal or whatever you want so it can help to make my concept clear about type casting in inheritance.
For reference, here's how this code might look in C++:
#include <string>
#include <utility>
#include <vector>
class Animal
{
std::string name_;
public:
explicit Animal(std::string name) : name_(std::move(name)) {}
virtual ~Animal() {}
};
class Cat : public Animal { using Animal::Animal; };
class Dog : public Animal { using Animal::Animal; };
class AnimalQueue
{
std::vector<Cat> cats_;
std::vector<Dog> dogs_;
public:
void Enqueue(Animal const & animal)
{
if (Cat const * p = dynamic_cast<Cat const *>(&animal))
{
cats_.push_back(*p);
}
else if (Dog const * p = dynamic_cast<Dog const *>(&animal))
{
dogs_.push_back(*p);
}
else
{
// discarding unrecognized animal
}
}
};
Usage:
AnimalQueue q;
q.Enqueue(Dog("dog"));
q.Enqueue(Cat("cat"));
Notes:
C++ basics:
Don't say using namespace std.
The container of choice is std::vector, not std::list.
Avoid implicit conversions. Everything is explicit unless required otherwise.
The string-sink constructor moves from its argument.
Adopt systematic naming conventions for class data members.
No need for loads of local variables; you can put arbitrary expressions into function calls.
My concrete classes inherit constructors for reasons of laziness. In a real setting, you may need to write your own constructors.
Polymorphism:
The polymorphic base has a virtual destructor.
Polymorphism can be used when arguments are passed as pointers or references to a base subobjects.
High-level design:
As written, there seems little reason to have a polymorphic base, since your entire code is static. Several distinct overloads (for Cat and Dog) would be more appropriate.
Polymorphic bases are needed when the concrete type cannot be known until runtime. In that case you won't have concrete-typed variables, and you will need to create objects dynamically. When that happens, you will want to pass around std::unique_ptr<Animal>, and the dynamic casts will have to be adjusted.
There are two problems that are fairly evident in your code:
You are not allowing dynamic binding
You have a slicing problem.
Dynamic binding
Dynamic binding is when a name is bound to a function at runtime rather than compile time. If you are dealing with runtime polymorphism, using dynamic binding allows you call functions using the dynamic type of the object (Dog) rather than its static type (Animal). This is useful because when derived classes override inherited base class functions, it is preferable to call the derived class function rather than the base class one.
To achieve dynamic binding in C++, you need to incorporate virtual functions. If you use virtual functions, the compiler will delay evaluating the name of the function until runtime where it can use the object's virtual table1 to bind the name to the address of the correct function.
To give getname() dynamic binding, declare it with the virtual specifier:
virtual string getname();
If a derived class overrides this function, that will be the one that is invoked, otherwise the base class's version will be called. This virtual function can be thought of as a default implementation.
The Slicing Problem
Slicing occurs when you copy the base part of a derived class instance. This can happen for instance when you take a base class argument by value and pass in a derived class - the derived part will be "sliced" off. When that happens you only have the static part of the object off of which to call functions and access data - hence why calling getname() in Enqueue() always calls Animal::getname().
To prevent this, you must use either a reference or pointer to a base class. This prevents slicing because no copying occurs when passing around references or pointers.
Make Enqueue take an lvalue-reference to an Animal instance:
void Enqueue(Animal const& a);
Important: If you are using base class pointer to a derived instance, in order to prevent Undefined Behavior, you must give the base class a virtual destructor. Doing so allows the derived class' destructor to be called along with the base class' destructor.
This is simply an explanation of your issues, you can refer to #Kerrek SB's answer for a good solution.
1 Virtual tables are a non-standard implementation, it really depends on your system how virtual function names are resolved.
Related
I'm having a rough time with a particular C++ inheritance problem. Say we have two abstract classes, one using the other as argument type for one of the pure virtual functions:
class Food {
public:
int calories=0;
virtual void set_calories(int cal)=0;
}
class Animal {
public:
int eaten_calories=0;
virtual void eat_food(Food &f)=0;
}
Now, we create a derived class for each, and we instantiate a virtual function with arguments of type the derived class:
class Vegetables: public Food{
public:
void set_calories(int cal){calories=cal;}
}
class Cow: public Animal{
public:
void eat_food(Vegetables &v){this->eaten_calories += v.calories;}
}
The problem with this is that the function eat_food requires a signature with the abstract class Food, or else a Cow() object creation won't compile, complaining that Cow is an abstract class because no suitable implementation of eat_food(Food f) was found.
Update: An additional constraint I seek for the implementation is that a second class Meat: public Food should not be usable with Cow::eat_food(f). In short, just setting Cow::eat_food(Food f) and casting to Vegetables wouldn't cut it.
What is the best way to overcome this error?
So far I have found two options:
Creating an eat_food(Food f) implementation in Cow with a try/catch to check if f can be safely casted to Vegetables, and then calling eat_food(Vegetables v). PROBLEM: if you have 50 virtual functions, this forces you to write 50 additional function implementations in Cow.
Turn the Animal into a Template class Animal<T>, and instantiate it with each of the derived classes of Food to define the animals (e.g., class Cow: public Animal<Vegetables>). PROBLEM: you can no longer define an Animal* pointer to hold an undefined animal with not known type.
Is there any viable/stylish alternative to these two? Maybe a software pattern of some kind?
When you defined the virtual function Animal::eat_food() accepting a Food& parameter, you declared that for any Animal, you can provide any Food to eat_food(). Now you want to break that promise. This brings into question your design. Either it is legitimate to call ptr->eat_food(food) where ptr is an Animal* and food is a Meat, or eat_food() should (probably) not be defined in the Animal class. If you cannot substitute one Food for another, use of Food& is likely a mistake. If you cannot substitute one Animal for another, defining at the Animal level is likely a mistake.
Perhaps a small change in nomenclature would help this make more sense. Consider renaming eat_food to give_food, or perhaps feed. Now you have a concept that is applicable to all animals. You can feed any food to any animal, but whether or not the animal eats it is a different story. Maybe you should make your virtual function feed() so that it applies equally well to all animals. If you have an Animal* and a Food&, you can feed the animal, but it's the animal that decides if it eats. If you were to instead insist that you must know the correct type of Food before feeding the Animal, then you should have a Cow* instead of an Animal*.
Note: If you happen to be in a case where you never try to feed an Animal*, then you could remove the virtual function from Animal, in which case your question becomes moot.
This might look something like the following.
class Animal {
int eaten_calories=0;
protected:
void eat_food(Food &f) { eaten_calories += f.calories; } // Not virtual
public:
virtual void feed(Food &f)=0;
};
class Cow: public Animal{
public:
void feed(Food &f) override {
// Cows only eat Vegetables.
if ( dynamic_cast<Vegetables*>(&f) ) // if `f` is a Vegetables
eat_food(f);
else
stampede(); // Or whatever you think is amusing (or appropriate).
}
};
Note that I have kept your eat_food() implementation, but moved it to a non-virtual function in Animal. This is based on an assumption, so it might be inappropriate. However, I am willing to assume that no matter what type of animal, and no matter what type of food, if the animal actually eats the food, then the eaten calories should increase by the food's calories.
In addition, a rule of thumb says that this might be the correct level of abstraction -- the two bits of data being used, calories and eaten_calories, belong directly to the two classes being used, Animal and Food. This suggests (just a rule of thumb) that your logic and data are at a consistent level of abstraction.
Oh, I also specified protected access for eat_food(). This way it is the object's decision whether or not to eat. No one will be able to force an animal to eat; they would only be able to offer it food. This demonstrates another principle of polymorphic design: when derived classes differ, only the objects of those classes should need to be aware of those differences. Code that sees only objects of a common base should not need to test for these differences in advance of using those objects.
If you pass around a polymorphic type (like Vegetables) as a base type by value (like Food f), you will slice the object, which prevents overriden methods from being called.
You need to pass such types by pointer or by reference instead, eg:
class Food {
public:
virtual int get_calories() const = 0;
};
class Animal {
public:
int eaten_calories = 0;
virtual void eat_food(Food& f) = 0;
};
class Vegetables: public Food {
public:
int get_calories() const { return ...; }
};
class Cow: public Animal{
public:
void eat_food(Food& f){ this->eaten_calories += f.get_calories(); }
};
Vegetables veggies;
Cow cow;
cow.eat_food(veggies);
UPDATE:
You can't change the signature of a virtual method in derived classes (except when using covariant return types). Since eat_food() is exposed in Animal and takes a Food&, if you want Cow::eat_food() to accept only a Vegetables object and not a Meat object, then it needs to check at runtime if the input Food& refers to a Vegetables object and if not then throw an exception. dynamic_cast does exactly that for you when casting a reference, eg:
class Cow: public Animal{
public:
void eat_food(Food& f){ this->eaten_calories += dynamic_cast<Vegetables&>(f).calories; }
};
Vegetables veggies;
Meat meat;
Cow cow;
cow.eat_food(veggies); // OK
cow.eat_food(meat); // throws std::bad_cast
I was looking at several SO posts (listed below) regarding the benefit of using base class pointer to a derived class object. But in most of the cases, virtual function is the ultimate purpose of using base class pointer. I added comments to some of these posts, but I guess since the posts are old, responses were not received.
Now my question is, if we do not use virtual function concept, are there any purpose of using base class pointer in some other case?
In the code below,
pEmp->computeTotalSalary
calls base class function since virtual function is missing. This is expected behavior.
#include <iostream>
using namespace std;
class Employee
{
public:
void computeTotalSalary ()
{
cout<<"Computing Employee Salary in Base Class:"<<endl;
}
};
class TeachingStaff : public Employee
{
public:
// Override the function
void computeTotalSalary ()
{
cout<<"Computing Teacher's Salary in Sub class: "<<endl;
}
};
int main()
{
TeachingStaff *pTeacher = new TeachingStaff() ;
pTeacher->computeTotalSalary();
Employee *pEmp;
pEmp = pTeacher;
pEmp->computeTotalSalary();
pTeacher->Employee::computeTotalSalary();
}
Links:
1. Why use base class pointers for derived classes
A Base Class pointer can point to a derived class object. Why is the vice-versa not true?
assigning derived class pointer to base class pointer in C++
Using a base class pointer or reference allows you to write functions that accept all derived classes of the base generically so you can call common non-virtual functions on them. Otherwise, you'd have to write the same function multiple times for the different derived classes, or use templates.
#include <iostream>
class base_t {
public:
void non_virtual() const { std::cout << "Hello, World!\n"; }
};
class derived_1_t : public base_t { };
class derived_2_t : public base_t { };
void do_something(const base_t& obj) {
obj.non_virtual();
}
int main() {
derived_1_t var1;
derived_2_t var2;
do_something(var1);
do_something(var2);
}
While you can intentionally hide functions from the base class, it is most often an unintentional mistake (or poor design) to do so. The C++11 override keyword was introduced to help prevent this mistake.
There are other use cases for inheritance beyond virtual functions and polymorphism. For instance: (1) one might put a bunch of objects in a heterogeneous container such as std::vector<Employee*> where it doesn't need access to the derived class data, though this is probably suspect without polymorphism also, (2) inheriting behavior or POD data members (also questionable practice), or (3) inheriting for policy-based design (see Alexandrescu's Modern C++ Design).
Generally, you also want a destructor for inheritance roots. Herb Sutter says, "A base class destructor should be either public and virtual, or protected and nonvirtual."
You might also consider not using inheritance in this way. See "Better Code: Runtime Polymorphism" by Sean Parent, which may just blow your mind.
I have a question about creating classes from an abstract class and how data gets cut.
Let's say we have an abstract class called Animal, and classes called Cat and Dog that implement said class. Both these classes implement a method from Animal called update(); however, in their update methods they access private methods and/or variables that are exclusive to themselves and not the Animal class. I understand that if we declare the classes in this manner...
Animal* dog = new Dog();
Animal* cat = new Cat();
We're only able to access methods or variables that only the Animal class specifically has; however, what if I called the update() method on each class instead, and this update method calls on the exclusive members in Cat and Dog. Would that be legal, or would this data be truncated because I created them as Animal?
The language does not force you to use only the polymorphic access to method 'update()'.
Example:
class Animal {
public:
virtual void update() { std::cout << "Animal::update() " << std::endl; }
virtual ~Animal(){}
};
class Cat : public Animal {
public:
virtual ~Cat(){}
virtual void update() { std::cout << "Cat::update() " << std::endl; }
};
class Dog : public Animal {
public:
virtual ~Dog(){}
virtual void update() { std::cout << "Dog::update() " << std::endl; }
};
int t395(void)
{
Animal* dog = new Dog();
Animal* cat = new Cat();
dog->update();
cat->update();
dog->Animal::update();
return (0);
}
// OUTPUT:
// Dog::update()
// Cat::update()
// Animal::update()
...We're only able to access methods or variables that only the Animal
class specifically has;
I agree ... dog is an Animal, and does not have a method Bark, and thus would not be able to invoke dog->bark(). But, you could add a method "virtual void talk()" to all three, and perhaps a virtual void Dog::talk() would simply invoke its local Dog::bark() method, and Cat::talk() would simply invoke it's local Cat::meow() method.
however, what if I called the update() method on each class instead,
and this update method calls on the exclusive
members in Cat and Dog. Would that be legal, or would this data be
truncated because I created them as Animal?
Legal - yes. Data is NOT truncated (in either Animal or Dog or Cat)
a) The polymorphic dog is-a Animal, and has all methods and data attributes of Animal.
b) It also has all the methods and attributes of Dog.
Implementation is compiler specific, but one typical impl. is that the two structures (there are some complication needing compiler attention) are simply concatenated in memory. Which is first doesn't matter - its an implementation issue.
Both cat and dog instances have access to their own data and method attributes, regardless of if these method are not mapped into the polymorphic table.
Also, both cat and dog instances have access to those parts of the parent Animal instance that are public or protected (but not private).
Not sure I fully understand your question, but your update() describes a virtual function call.
I suspect you are having problems understanding how inheritance and polymorphism is implemented, I know I did. Consider the following:
class base
{
private:
int mylocalInt; //inaccessible to anyone but the base.
protected:
int sharedInt = 5;//accessible by base, and any subtype.
public:
base()
{
cout<<"creating base object"<<endl;
}
virtual ~base()
{
cout<<"Now destroying base object"<<endl;
}
void virtual callMe()//will be overridden, only called if you directly instantiate a base object.
{
cout<<"I am a base"<<endl;
}
};
class subtypeA : public base
{
private:
int Aint;
public:
subtypeA()
{
cout<<"creating subtype"<<endl;
}
~subtypeA()
{
cout<<"destroying subtype"<<endl;
}
void callMe()
{
cout<<"I am a subtypeA"<<endl;
}
int getAint()//this is a local, IE static function, a base ptr cannot access it.
{
return Aint;
}
int getSharedInt()//notice how sharedInt, located in the base object, is still accessible from within the subtype.
{
return sharedInt;
}
};
int main(int argc, char* argv[] )
{
base* ptr = new subtypeA;
ptr->callMe();//works fine, will check which subtype, if any, ptr points to, and call the appropriate callMe(). This is because
//callMe() is virtual in base.
//ptr->sharedInt//illegal, main is not part of base or a subtype of base.
subtypeA* Aptr = (subtypeA*)ptr;//since all pointers are the same size, they can be cast to one another, is dangerous however
cout<<Aptr->getSharedInt()<<endl;//works, getSharedInt is NOT virtual, but a normal static member of subtypeA, so in order to use it, the pointer
//needs to be of type subtypeA. the sharedInt however is protected, so subtypeA can access it due to the fact that it is related to it's owner, base.
}
Now take that, and play around with it, add a subtypeB, then add subtype to that subtype, IE subtypeAA and BB for instance.
Notice that each individual class is still it's own object, distinct from any of the objects it is related to. So if a variable is private, it can't be directly accessed from the outside, just as with normal objects.
Again: There is nothing truly special about polymorphism, all it is is a nice abstraction hiding the "ugly" type-checking and so forth going on to facilitate virtual calls.
I completely forgot about your other question. No, you never have to worry about truncation in this case. In fact I asked more or less the same question some time ago, take a look: C++ subtype degeneration when placed in a container
dasblinkenlight explains it brilliantly.
I am confused about the concepts of inheritance and polymorphism. I mean, what is the difference between code re-usability and function overriding? Is it impossible to reuse parent class function using inheritance concept or else is it impossible to override parent class variables using Polymorphism. There seems little difference for me.
class A
{
public:
int a;
virtual void get()
{
cout<<"welcome";
}
};
class B:public A
{
a =a+1; //why it is called code reuse
void get() //why it is called overriding
{
cout<<"hi";
}
};
My doubt is about the difference between the code reuse and function overriding.
Lets start with your example.
class A
{
public:
int a;
virtual void get()
{
cout<<"welcome";
}
};
class B:public A
{
a =a+1; //why it is called code reuse
void get() //why it is called overriding
{
cout<<"hi";
}
};
Inheritance: Here you are deriving class B from class A, this means that you can access all of its public variables and method.
a = a + 1
Here you are using variable a of class A, you are reusing the variable a in class B thereby achieving code reusability.
Polymorphism deals with how a program invokes a method depending on the things it has to perform: in your example you are overriding the method get() of class A with method get() of class B. So when you create an instance of Class B and call method get you'll get 'hi' in the console not 'welcome'
Function inheritance allows for abstraction of behaviour from a "more concrete" derived class(es) to a "more abstract" base class. (This is analogous to factoring in basic math and algebra.) In this context, more abstract simply means that less details are specified. It is expected that derived classes will extend (or add to) what is specified in the base class. For example:
class CommonBase
{
public:
int getCommonProperty(void) const { return m_commonProperty; }
void setCommonProperty(int value) { m_commonProperty = value; }
private:
int m_commonProperty;
};
class Subtype1 : public CommonBase
{
// Add more specific stuff in addition to inherited stuff here...
public:
char getProperty(void) const { return m_specificProperty1; }
private:
char m_specificProperty1;
};
class Subtype2 : public CommonBase
{
// Add more specific stuff in addition to inherited stuff here...
public:
float getProperty(void) const { return m_specificProperty2; }
private:
float m_specificProperty2;
};
Note that in the above example, getCommonProperty() and setCommonProperty(int) are inherited from the CommonBase class, and can be used in instances of objects of type Subtype1 and Subtype2. So we have inheritance here, but we don't really have polymorphism yet (as will be explained below).
You may or may not want to instantiate objects of the base class, but you can still use it to collect/specify behaviour (methods) and properties (fields) that all derived classes will inherit. So with respect to code reuse, if you have more than one type of derived class that shares some common behaviour, you can specify that behaviour only once in the base class and then "reuse" that in all derived classes without having to copy it. For example, in the above code, the specifications of getCommmonProperty() and setCommonProperty(int) can be said to be reused by each Subtype# class because the methods do not need to be rewritten for each.
Polymorphism is related, but it implies more. It basically means that you can treat objects that happen to be from different classes the same way because they all happen to be derived from (extend) a common base class. For this to be really useful, the language should support virtual inheritance. That means that the function signatures can be the same across multiple derived classes (i.e., the signature is part of the common, abstract base class), but will do different things depending on specific type of object.
So modifying the above example to add to CommonBase (but keeping Subtype1 and Subtype2 the same as before):
class CommonBase
{
public:
int getCommonProperty(void) const { return m_commonProperty; }
void setCommonProperty(int value) { m_commonProperty = value; }
virtual void doSomething(void) = 0;
virtual ~CommonBase() { }
private:
int m_commonProperty;
};
Note that doSomething() is declared here as a pure virtual function in CommonBase (which means that you can never instantiate a CommonBase object directly -- it didn't have to be this way, I just did that to keep things simple). But now, if you have a pointer to a CommonBase object, which can be either a Subtype1 or a Subtype2, you can call doSomething() on it. This will do something different depending on the type of the object. This is polymorphism.
void foo(void)
{
CommonBase * pCB = new Subtype1;
pCB->doSomething();
pCB = new Subtype2;
pCB->doSomething(); // Does something different...
}
In terms of the code sample you provided in the question, the reason get() is called "overriding" is because the behaviour specified in the B::get() version of the method takes precedence over ("overrides") the behaviour specified in the A::get() version of the method if you call get() on an instance of a B object (even if you do it via an A*, because the method was declared virtual in class A).
Finally, your other comment/question about "code reuse" there doesn't quite work as you specified it (since it's not in a method), but I hope it will be clear if you refer to what I wrote above. When you are inheriting behaviour from a common base class and you only have to write the code for that behaviour once (in the base class) and then all derived classes can use it, then that can be considered a type of "code reuse".
You can have parametric polymorphism without inheritance. In C++, this is implemented using templates. Wiki article:
http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29#Parametric_polymorphism
I was wondering whether a design pattern or idiom exists to automatically register a class type. Or simpler, can I force a method to get called on a class by simply extending a base class?
For example, say I have a base class Animal and extending classes Tiger and Dog, and I have a helper function that prints out all classes that extend Animal.
So I could have something like:
struct AnimalManager
{
static std::vector<std::string> names;
static void registerAnimal(std::string name) {
//if not already registered
names.push_back(name); }
};
struct Animal
{
virtual std::string name() = 0;
void registerAnimal() { AnimalManager::registerAnimal(name()); }
};
struct Tiger : Animal
{
virtual std::string name() { return "Tiger"; }
};
So basically I would do:
Tiger t;
t.registerAnimal();
This could be worked into a static function as well. Is there any pattern (like a curiously recursive template) or something like that that can help me achieve this without explicitly having to call the registerAnimal method.
I want my class Animal to be extendible in the future and others might forget to call register, I'm looking for ways to prevent that besides documenting this (which I will anyway).
PS This is just an example, I'm not actually implementing animals.
You can indeed do this using the curiously recursive template idiom. It requires nothing from whoever is extending the class that can't be enforced by the compiler:
template<class T>
struct Animal
{
Animal()
{
reg; //force specialization
}
virtual std::string name() = 0;
static bool reg;
static bool init()
{
T t;
AnimalManager::registerAnimal(t.name());
return true;
}
};
template<class T>
bool Animal<T>::reg = Animal<T>::init();
struct Tiger : Animal<Tiger>
{
virtual std::string name() { return "Tiger"; }
};
In this code, you can only extend Animal if you specialize it. The constructor forces the static member reg to be initialized, which in turn calls the register method.
EDIT: As pointed out by #David Hammen in the comments, you won't be able to have a collection of Animal objects. However, this can easily be solved by having a non-template class from which the template inherits and use that as a base class, and only use the template for extending.
If you insist every animal should be registered, why not just make name a parameter of Animal constructor. Then you can put register issues to Animal constructor and every derived will have to pass valid name and register:
struct Animal
{
Animal(std::string name){ AnimalManager::registerAnimal(name);}
}
struct Tiger : Animal
{
Tiger():Animal("Tiger"){}
};
This is a typical example where you want to do some sort of bookkeeping when an object is constructed. Item 9 in Scott Meyers "Effective C++" gives an example of this.
Basically you move all the bookkeeping stuff to base class. Derived class explicitly constructs base class and passes the information that is required for Base class construction. For example:
struct Animal
{
Animal(std::string animal_type)
{
AnimalManager::registerAnimal(animal_type);
};
};
struct Dog : public Animal
{
Dog() : Animal(animal_type()) {};
private:
static std::string animal_type()
{
return "Dog";
};
};
Usually I do this with a macro.
Unit test frameworks often employ the technique for registering the tests, e.g. GoogleTest
#AMCoder: This is not the answer you want. The answer you want, reflection (e.g., what_am_I()) doesn't really exist in C++.
C++ has in a rather limited form via the RTTI. Using RTTI in the base class to determine the "true" type of the object being constructed won't work. Calling typeid(*this) in a base class will instead give you the typeinfo for the class being constructed.
You can make your class Animal have a non-default constructor only. This works fine for classes that derive directly from Animal, but what about classes that derive from a derived class? This approach either precludes further inheritance or requires class builders to create multiple constructors, one of which is for use by derived classes.
You can use Luchian's CRTP solution, but this too has problems with inheritance, and it also precludes you from having a collection of pointers to Animal objects. Add that non-template base class back into the mix so you can have a collection of Animals and you have the original problem all over again. Your documentation will have to say to only use the template to make a class that derives from Animal. What happens if someone doesn't do that?
The easiest solution is the one you don't like: Require that every constructor of a class that derives from Animal must call register_animal(). Say so in your documentation. Show the users of your code some examples. Put a comment in front of that example code, // Every constructor must call register_animal(). People who use your code are going to use cut and paste anyhow, so have some cut-and-paste ready solutions on hand.
Worrying about what happens if people don't read your documentation is a case of premature optimization. Requiring that every class call register_animal() in their constructors is a simple requirement. Everyone can understand it and everyone can easily implement it. You've got much bigger troubles on your hands with your users than a failed registration if your users can't even follow this simple instruction.
You could just call a method in the base class constructor, which will get called everytime a derived class gets instantiated, as follows:
class Animal {
public:
Animal() {doStuff();}
}
The doStuff() method could be implemented in the base class to do static operations, or it could be pure virtual and be implemented in derived classes.
Edit: As correctly pointed out in the comments, virtual methods cant be called in the ctor.
Notice though that the base class constructor will be called before the derived constructors, so you could also do something like this:
class Animal {
public:
Animal(const std::string &name) {doStuff(name);}
private:
Animal(); // Now nobody can call it, no need to implement
}
class Dog : public Animal {
Dog() : Animal("Dog") {}
}
Hope that helps