This question has already been answered:
- To render the template class method in .cpp 3 responses
Hello, I wrote a template like this. CompositeShape.hpp
class CompositeShape : public Shape { public: CompositeShape(); ~CompositeShape(); template<class T> void addComponent(T shape); void removeComponent(const int index = -1); // if don't input index, then method will remove last component virtual void move(const point_t &posTo) override; virtual void move(const double dx, const double dy) override; virtual void scale(const double coefficient); virtual double getArea() const; rectangle_t getFrameRect() const; int getLength() const; virtual void print(std::string name) const; private: int maxlength_; int length_; Shape **shapes_; void setPosition(); }; And it is described in CompositeShape.spp
#include "CompositeShape.hpp" CompositeShape::CompositeShape() : Shape({0,0}), maxlength_(5), length_(0) { shapes_ = new Shape *[maxlength_]; } CompositeShape::~CompositeShape() { delete[] shapes_; } void CompositeShape::removeComponent(const int index) { //TODO:FIXME if (length_ <= 0) { //TODO: message about exception return; } if (index == -1 && length_ > 0) { shapes_[--length_] = nullptr; if (length_ > 0) { setPosition(); } } if (index < length_ && index >= 0 && length_ > 0) { shapes_[index] = nullptr; for (int i = index; i < length_ - 1; i++) { shapes_[i] = shapes_[i + 1]; } shapes_[--length_] = nullptr; if (length_ > 0) { setPosition(); } } else { // TODO: massege about exception } } void CompositeShape::move(const point_t &posTo) { if (length_ <= 0) { //TODO: massage about exception return; } setPosition(); move(posTo.x - position_.x, posTo.y - position_.y); } void CompositeShape::move(const double dx, const double dy) { if (length_ <= 0) { //TODO: massage about exception return; } setPosition(); position_.x += dx; position_.y += dy; //FIXME: for (int i = 0; i < length_; i++) { shapes_[i]->move(dx, dy); } } void CompositeShape::scale(const double coefficient) { if (length_ <= 0) { //TODO: massage about exception return; } setPosition(); for (int i = 0; i < length_; i++) { shapes_[i]->move({position_.x + coefficient * (shapes_[i]->getPosition().x - position_.x), position_.y + coefficient * (shapes_[i]->getPosition().y - position_.y)});//FIXME: shapes_[i]->scale(coefficient); } } double CompositeShape::getArea() const { if (length_ <= 0) { //TODO: massage about exception return -1; } double area = 0; for (int i = 0; i < length_; i++) { area += shapes_[i]->getArea(); } return area; } rectangle_t CompositeShape::getFrameRect() const { if (length_ <= 0) { //TODO: massage about exception return {{0, 0}, -1, -1}; } double left = shapes_[0]->getPosition().x - shapes_[0]->getFrameRect().width / 2; double right = shapes_[0]->getPosition().x + shapes_[0]->getFrameRect().width / 2; double top = shapes_[0]->getPosition().y + shapes_[0]->getFrameRect().height / 2; double bottom = shapes_[0]->getPosition().y - shapes_[0]->getFrameRect().height / 2; for (int i = 1; i < length_; i++) { if ((shapes_[i]->getPosition().x - shapes_[i]->getFrameRect().width / 2) < left) { left = shapes_[i]->getPosition().x - shapes_[i]->getFrameRect().width / 2; } if ((shapes_[i]->getPosition().x + shapes_[i]->getFrameRect().width / 2) > right) { right = shapes_[i]->getPosition().x + shapes_[i]->getFrameRect().width / 2; } if ((shapes_[i]->getPosition().y + shapes_[i]->getFrameRect().height / 2) > top) { top = shapes_[i]->getPosition().y + shapes_[i]->getFrameRect().height / 2; } if ((shapes_[i]->getPosition().y - shapes_[i]->getFrameRect().height / 2) < bottom) { bottom = shapes_[i]->getPosition().y - shapes_[i]->getFrameRect().height / 2; } } return {{(left + (right - left) / 2), (bottom + (top - bottom) / 2)}, (right - left), (top - bottom)}; } void CompositeShape::setPosition() { if (length_ > 0) { position_ = getFrameRect().pos; } } int CompositeShape::getLength() const { return length_; } void CompositeShape::print(std::string name) const { std::cout << name << std::endl; for (int i = 0; i < length_; i++) { shapes_[i]->print("from composite shape"); } } template <class T> void CompositeShape::addComponent(T shape) { //TODO:FIXME if (std::is_base_of<Shape,T>::value){ std::cout << "Exception: can add not Shape element" << std::endl; return; } if (length_ < maxlength_) { Shape *shape1 = new T(shape); shapes_[length_] = shape1; length_++; setPosition(); } else { Shape **shapes1 = shapes_; shapes_ = new Shape *[maxlength_ + 5]; for (int i = 0; i < maxlength_; i++) { shapes_[i] = shapes1[i]; } delete[] shapes1; maxlength_ += 5; addComponent(shape); } } Moreover, if you write such a year in main
#include "CompositeShape.hpp" # include "rectangle.hpp" Rectangle rect1 = Rectangle({0, 0}, 10, 10); then we get an error
CompositeShape compositeShape; compositeShape.addComponent(rect1); undefined reference to void CompositeShape::add component <Rectangle>(Rectangle) How can this be fixed?