--- /dev/null
+#include "Animal.h"
+#include <string>
+#include <iostream>
+
+Animal::Animal(std::string type)
+ : m_type(type)
+{
+ std::cout << "Animal default cstr\n";
+}
+
+Animal::Animal(const Animal &other)
+{
+ std::cout << "Animal copy cstr\n";
+ *this = other;
+}
+
+Animal::~Animal()
+{
+ std::cout << "Animal destr\n";
+}
+
+Animal &Animal::operator=(const Animal &other)
+{
+ if (this == &other)
+ return (*this);
+ return (*this);
+}
+
+// This would better be purely virtual function but the subject mandates that
+// even the base must implement this function.
+void Animal::makeSound() const
+{
+ std::cout << "BASE ANIMAL SOUNDS\n";
+}
+
+std::string Animal::getType() const
+{
+ return (m_type);
+}
--- /dev/null
+#ifndef ANIMAL_H
+# define ANIMAL_H
+
+# include <string>
+
+class Animal
+{
+ protected:
+ std::string m_type;
+
+ public:
+ Animal(std::string type = "BASE");
+ Animal(const Animal &other);
+ virtual ~Animal();
+
+ virtual Animal &operator=(const Animal &other);
+
+ virtual void makeSound() const;
+ std::string getType() const;
+ virtual void listIdeas() const = 0;
+ virtual void addIdea(std::string idea) = 0;
+};
+
+#endif // ANIMAL_H
--- /dev/null
+#include "Brain.h"
+#include <string>
+#include <iostream>
+
+Brain::Brain()
+ : m_is_full(0)
+ , m_index(0)
+{
+ std::cout << "Brain default cstr\n";
+}
+
+Brain::Brain(const Brain &other)
+{
+ std::cout << "Brain copy cstr\n";
+ *this = other;
+}
+
+Brain::~Brain()
+{
+ std::cout << "Brain destr\n";
+}
+
+Brain &Brain::operator=(const Brain &other)
+{
+ if (this == &other)
+ return (*this);
+ m_is_full = other.m_is_full;
+ for (m_index = 0;
+ (m_is_full && m_index < CAPACITY) || (m_index < other.m_index);
+ ++m_index)
+ m_ideas[m_index] = other.m_ideas[m_index];
+ m_index = other.m_index;
+ return (*this);
+}
+
+void Brain::addIdea(std::string idea)
+{
+ m_ideas[m_index] = idea;
+ ++m_index;
+ if (m_index == CAPACITY)
+ {
+ m_is_full = 1;
+ m_index = 0;
+ }
+}
+
+void Brain::listIdeas() const
+{
+ if (m_is_full)
+ {
+ std::cout << m_ideas[m_index] << '\n';
+ for(size_t i((m_index + 1) % CAPACITY); i != m_index; i = (i + 1) % CAPACITY)
+ std::cout << m_ideas[i] << '\n';
+ }
+ else
+ for(size_t i(0); i < m_index; ++i)
+ std::cout << m_ideas[i] << '\n';
+}
--- /dev/null
+#ifndef BRAIN_H
+# define BRAIN_H
+
+# include <string>
+
+class Brain
+{
+ private:
+ static const size_t CAPACITY = 100;
+
+ bool m_is_full;
+ size_t m_index;
+ std::string m_ideas[CAPACITY];
+
+ public:
+ Brain();
+ Brain(const Brain &other);
+ ~Brain();
+
+ Brain &operator=(const Brain &other);
+
+ void addIdea(std::string idea);
+ void listIdeas() const;
+};
+
+#endif // BRAIN_H
--- /dev/null
+#include "Cat.h"
+#include <iostream>
+
+Cat::Cat()
+ : Animal("Cat")
+ , m_brain(new Brain)
+{
+ std::cout << "Cat default cstr\n";
+}
+
+Cat::Cat(const Cat &other)
+ : Animal("Cat")
+ , m_brain(new Brain)
+{
+ std::cout << "Cat copy cstr\n";
+ *this = other;
+}
+
+Cat::~Cat()
+{
+ std::cout << "Cat destr\n";
+ delete m_brain;
+}
+
+Animal &Cat::operator=(const Animal &other)
+{
+ const Cat *ptr(dynamic_cast<const Cat *>(&other));
+
+ if (this == &other)
+ return (*this);
+ if (ptr)
+ *m_brain = *ptr->m_brain;
+ return (*this);
+}
+
+void Cat::makeSound() const
+{
+ std::cout << "Meow :3\n";
+}
+
+void Cat::addIdea(std::string idea)
+{
+ m_brain->addIdea(idea);
+}
+
+void Cat::listIdeas() const
+{
+ m_brain->listIdeas();
+}
--- /dev/null
+#ifndef CAT_H
+# define CAT_H
+
+# include "Animal.h"
+# include "Brain.h"
+
+class Cat : public Animal
+{
+ private:
+ Brain *m_brain;
+
+ public:
+ Cat();
+ Cat(const Cat &other);
+ ~Cat();
+
+ Animal &operator=(const Animal &other);
+
+ void makeSound() const;
+ void listIdeas() const;
+ void addIdea(std::string idea);
+};
+
+#endif // CAT_H
--- /dev/null
+#include "Dog.h"
+#include <iostream>
+
+Dog::Dog()
+ : Animal("Dog")
+ , m_brain(new Brain)
+{
+ std::cout << "Dog default cstr\n";
+}
+
+Dog::Dog(const Dog &other)
+ : Animal("Dog")
+ , m_brain(new Brain)
+{
+ std::cout << "Dog copy cstr\n";
+ *this = other;
+}
+
+Dog::~Dog()
+{
+ std::cout << "Dog destr\n";
+ delete m_brain;
+}
+
+Animal &Dog::operator=(const Animal &other)
+{
+ const Dog *ptr(dynamic_cast<const Dog *>(&other));
+
+ if (this == &other)
+ return (*this);
+ if (ptr)
+ *m_brain = *ptr->m_brain;
+ return (*this);
+}
+
+void Dog::makeSound() const
+{
+ std::cout << "Bark!\n";
+}
+
+void Dog::addIdea(std::string idea)
+{
+ m_brain->addIdea(idea);
+}
+
+void Dog::listIdeas() const
+{
+ m_brain->listIdeas();
+}
--- /dev/null
+#ifndef DOG_H
+# define DOG_H
+
+# include "Animal.h"
+# include "Brain.h"
+
+class Dog : public Animal
+{
+ private:
+ Brain *m_brain;
+
+ public:
+ Dog();
+ Dog(const Dog &other);
+ ~Dog();
+
+ Animal &operator=(const Animal &other);
+
+ void makeSound() const;
+ void listIdeas() const;
+ void addIdea(std::string idea);
+};
+
+#endif // DOG_H
--- /dev/null
+CC := clang++
+CFLAGS = -std=c++98 -Wall -Wextra -Werror -Wpedantic
+
+DEP_GEN = g++ -MM
+
+ifneq ("$(wildcard .debug)","")
+ CFLAGS += -g -fno-limit-debug-info
+endif
+
+RM := rm -f
+
+INCDIR := inc
+INCDIR += $(addsuffix /inc, $(SUBPROJECTS));
+ifneq ($(INCLUDE),)
+ INCLUDE := $(addprefix -I, $(INCDIR))
+endif
+
+SRCDIR := .
+
+SOURCES := main.cpp \
+ Animal.cpp \
+ Cat.cpp \
+ Dog.cpp \
+ WrongAnimal.cpp \
+ WrongCat.cpp \
+ Brain.cpp \
+
+SOURCES := $(addprefix $(SRCDIR)/, $(SOURCES))
+
+OBJECTS := $(SOURCES:.cpp=.o)
+
+NAME := zoo
+
+all : $(NAME)
+
+debug : .debug
+ $(MAKE) all
+
+nodebug :
+ $(RM) .debug
+ $(MAKE) re
+
+.% :
+ $(MAKE) fclean
+ touch $@
+
+$(NAME) : $(OBJECTS)
+ $(CC) $(CFLAGS) -o $@ $^ $(LINKS)
+
+%.o : %.cpp
+ $(CC) $(CFLAGS) -o $@ -c $< $(INCLUDE)
+
+clean :
+ $(RM) $(OBJECTS)
+
+fclean : clean
+ $(RM) $(NAME)
+
+re : fclean
+ $(MAKE) all
+
+depend: .depend
+
+.depend: $(SOURCES)
+ rm -f $@
+ $(DEP_GEN) $^ > $@
+
+include .depend
--- /dev/null
+#include "WrongAnimal.h"
+#include <string>
+#include <iostream>
+
+WrongAnimal::WrongAnimal(std::string type)
+ : m_type(type)
+{
+ std::cout << "WrongAnimal default cstr\n";
+}
+
+WrongAnimal::WrongAnimal(const WrongAnimal &other)
+{
+ std::cout << "WrongAnimal copy cstr\n";
+ *this = other;
+}
+
+WrongAnimal::~WrongAnimal()
+{
+ std::cout << "WrongAnimal destr\n";
+}
+
+WrongAnimal &WrongAnimal::operator=(const WrongAnimal &other)
+{
+ if (this == &other)
+ return (*this);
+ return (*this);
+}
+
+// This would better be purely virtual function but the subject mandates that
+// even the base must implement this function.
+void WrongAnimal::makeSound() const
+{
+ std::cout << "BASE ANIMAL SOUNDS\n";
+}
+
+std::string WrongAnimal::getType() const
+{
+ return (m_type);
+}
--- /dev/null
+#ifndef WRONGANIMAL_H
+# define WRONGANIMAL_H
+
+# include <string>
+
+class WrongAnimal
+{
+ protected:
+ std::string m_type;
+
+ public:
+ WrongAnimal(std::string type = "BASE");
+ WrongAnimal(const WrongAnimal &other);
+ ~WrongAnimal();
+
+ WrongAnimal &operator=(const WrongAnimal &other);
+
+ void makeSound() const;
+ std::string getType() const;
+};
+
+#endif // WRONGANIMAL_H
--- /dev/null
+#include "WrongCat.h"
+#include <iostream>
+
+WrongCat::WrongCat()
+ : WrongAnimal("WrongCat")
+{
+ std::cout << "WrongCat default cstr\n";
+}
+
+WrongCat::WrongCat(const WrongCat &other)
+ : WrongAnimal("WrongCat")
+{
+ std::cout << "WrongCat copy cstr\n";
+ *this = other;
+}
+
+WrongCat::~WrongCat()
+{
+ std::cout << "WrongCat destr\n";
+}
+
+WrongCat &WrongCat::operator=(const WrongCat &other)
+{
+ if (this == &other)
+ return (*this);
+ return (*this);
+}
+
+void WrongCat::makeSound() const
+{
+ std::cout << "Meow :3\n";
+}
--- /dev/null
+#ifndef WRONGCAT_H
+# define WRONGCAT_H
+
+# include "WrongAnimal.h"
+
+class WrongCat : public WrongAnimal
+{
+ private:
+
+ public:
+ WrongCat();
+ WrongCat(const WrongCat &other);
+ ~WrongCat();
+
+ WrongCat &operator=(const WrongCat &other);
+
+ void makeSound() const;
+};
+
+#endif // WRONGCAT_H
--- /dev/null
+#include "Animal.h"
+#include "Cat.h"
+#include "Dog.h"
+#include "WrongAnimal.h"
+#include "WrongCat.h"
+#include <iostream>
+
+static const size_t SIZE = 4;
+
+int main()
+{
+ Animal *arr[SIZE];
+ Dog dog;
+ Cat cat;
+
+ dog.addIdea("Being constructed is fun.");
+ cat.addIdea("Being constructed is tiring.");
+ for (size_t i(0); i < SIZE / 2; ++i)
+ {
+ arr[i] = new Dog();
+ *arr[i] = dog;
+ }
+ for (size_t i(SIZE / 2); i < SIZE; ++i)
+ {
+ arr[i] = new Cat();
+ *arr[i] = cat;
+ }
+ arr[0]->addIdea("I'm the second dog alive. What a thrill.");
+ dog.addIdea("I'm not gonna be alone.");
+ arr[1]->addIdea("Wow, there are 2 other dogs. Hello.");
+ dog.addIdea("Being the prototype of so many is a great responsibility.");
+ arr[SIZE/2]->addIdea("Where is a high spot? I need to oversee the situation.");
+ arr[SIZE / 2 + 1]->addIdea("*YAWN* Why am I heWHAT IS THIS SHINY LITTLE THING?");
+ cat.addIdea("Clone me more, I am the ultimate being after all.");
+ dog.listIdeas();
+ cat.listIdeas();
+ for (size_t i(0); i < SIZE; ++i)
+ arr[i]->listIdeas();
+ for (size_t i(0); i < SIZE; ++i)
+ delete arr[i];
+ return (0);
+}