looogle
@looogle
Программист-любитель на C++ и по жизни.

Как правильно запутить конструктор родителя внутри наследника?

У меня есть 2 класса Node и LifeNode. Node -- шаблон класса.
Вот их объявление:
node.h
#ifndef NODE_H
#define NODE_H

#include <ros/ros.h>
#include <ros_johnny5/servoMsgArray.h>
#include <ros_johnny5/servoMsg.h>
#include <ros_johnny5/robotState.h>

template <typename PublisherMsgType, typename SubscriberMsgType>
class Node
{
private:
    ros::Publisher mPublisher;
    ros::Subscriber mSubscriber;
public:
    Node(int sizeMessageBuffer,
         char* publisherTopicName,
         char* subscriberTopicName);
    void publish(PublisherMsgType &msg);
    int getNumSubscribers();
protected:
    virtual void pCallbackFunc(const SubscriberMsgType &msg);
    ros::NodeHandle pNodeHandler;
};

#endif // NODE_H


life_node.h
#ifndef JOHNNY_LIFE_H
#define JOHNNY_LIFE_H

#include <ros/ros.h>
#include <ros_johnny5/servoMsgArray.h>
#include <ros_johnny5/servoMsg.h>
#include <ros_johnny5/robotState.h>
#include <node.h>
#include <topics.h>
#include <positions.h>

class LifeNode : public Node<ros_johnny5::servoMsgArray, ros_johnny5::robotState>
{
private:
    u_int8_t mInMotion;
    u_int8_t mGreetingFlag;
    ros::Timer greetingTimer;
public:
    LifeNode();
    void greetingTimerCallback(const ros::TimerEvent& e);
    void callbackFunc(const ros_johnny5::robotState &msg);
    void publish(ros_johnny5::servoMsgArray &msg);
    void timerInit();
    u_int8_t getMotion();
};

#endif // JOHNNY_LIFE_H

Вопрос в следующем: как правильно написать реализацию конструктора наследника?
Вот так сделал я:
#include life_node.h

LifeNode::LifeNode():
      Node(SIZE_MESSAGE_BUFFER, TOPIC_SERVO_CONTROL, TOPIC_ROBOT_STATE),
      mInMotion(1),
      mGreetingFlag(0)
{

}

Но получаю ошибку:
/home/dim/Dev/catkin_ws/src/ros_johnny5/src/johnny_life.cpp:12: ошибка: undefined reference to `Node<ros_johnny5::servoMsgArray_<std::allocator<void> >, ros_johnny5::robotState_<std::allocator<void> > >::Node(int, char*, char*)'


Как быть?
  • Вопрос задан
  • 2398 просмотров
Решения вопроса 2
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
#include life_node.h

LifeNode::LifeNode():
      Node<ros_johnny5::servoMsgArray, ros_johnny5::robotState>(SIZE_MESSAGE_BUFFER, TOPIC_SERVO_CONTROL, TOPIC_ROBOT_STATE),
      mInMotion(1),
      mGreetingFlag(0)
{

}

Кроме того, конструктор Node должен либо быть определён в файле node.h (или любом другом, который должен быть подключен к моменту вызова конструктора), либо явно инстанцирован для использованных вами шаблонных параметров. Это относится также и ко всем методам класса Node.
Ответ написан
Комментировать
dnovikoff
@dnovikoff
Вы получаете ошибку этапа компоновки (linking), а не ошибку этапа компиляции (compile).

Смысл ошибки в том, что отсутсвует определение конструктора для класса Node<ros_johnny5::servoMsgArray, ros_johnny5::robotState> (да - именно так. с кнонкретными параметрами). Его нет в заголовочном файле и он не прилинкован из другого объектного файла/библиотеки.

Принято для шаблонов совмещать объявление и опредление функций. То есть в том месте, где у вас есть объявление, должно быть и тело конструктора.

Конечно вы можете написать реализацию отдельно (экспорт шаблонов), но тогда вам придется компилировать их отдельно с каждым набором используемых у вас параметров, т.к. это будут разные классы. Или подключать реализацию туда же куда и заголовок. Но это значит плодить лишний файл и раздувать код ради ничего.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
LestaD
@LestaD
Веб разработчик
Наследник также должен быть шаблонным
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы