If you combine definition and implementation, you will have problems resolving cross-circular dependencies.
For instance:
1. Using the second option
home.hpp
#ifndef HOME_HPP # define HOME_HPP # include <string> # include "human.hpp" template <typename T> class Home { public: Home() : color_("white"), inhabitant_(this) { } void set_color(const std::string& color) { color_ = color; } private: std::string color_; Human<T> inhabitant_; }; #endif
human.hpp
#ifndef HUMAN_HPP # define HUMAN_HPP # include <string> // Cannot include the other header here because it already includes us //# include "house.hpp" // So we do a forward declaration: template<typename T> class Home; template <typename T> class Human { public: Human(Home<T>* house) : house_(house) { } void paint(const std::string& color) { // Oops, we can't use House in our implementation // because it is only forward declared //house_->set_color(color); } private: Home<T>* house_; }; #endif
You cannot use another object.
If you split your implementation in another file:
2. Using the first option
home.hpp
#ifndef HOME_HPP # define HOME_HPP # include <string> # include "human.hpp" template <typename T> class Home { public: Home(); void set_color(const std::string& color); private: std::string color_; Human<T> inhabitant_; }; #endif
home.ipp
#ifndef HOME_IPP # define HOME_IPP # include "home.hpp" template<typename T> Home<T>::Home() : color_("white"), inhabitant_(this) { } template<typename T> void Home<T>::set_color(const std::string& color); { color_ = color; } #endif
human.hpp
#ifndef HUMAN_HPP # define HUMAN_HPP # include <string> template<typename T> class Home; template <typename T> class Human { public: Human(Home<T>* house); void paint(const std::string& color); private: Home<T>* house_; }; #endif
human.ipp
#ifndef HUMAN_IPP # define HUMAN_IPP # include "human.hpp" # include "house.ipp" template<typename T> Human<T>::Human(Home<T>* house) : house_(house) { } template<typename T> void Human<T>::paint(const std::string& color) { house_->set_color(color); } #endif
Everything works more smoothly
3. Other considerations
- You could also argue that you should put your code in multiple files for the same reason that you are not encoding the entire project in one file, just to separate things to make them more understandable.
- And as the last bonus point for symmetry with .hpp / .cpp files, which will make the perfectionist sleep deeply (very deeply for some) inside each developer :)
source share