LINUX.ORG.RU

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

 , ,


0

2

У меня есть 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/life_node.cpp:12: ошибка: undefined reference to `Node<ros_johnny5::servoMsgArray_<std::allocator<void> >, ros_johnny5::robotState_<std::allocator<void> > >::Node(int, char*, char*)'

Что я делаю не так?



Последнее исправление: looogle (всего исправлений: 2)

Что я делаю не так?

Ты забыл написать или прилинковать реализацию Node<>::Node(int, char*, char*).

Deleted
()
Ответ на: комментарий от Deleted

Ты забыл написать или прилинковать реализацию Node<>::Node(int, char*, char*).

Реализация у меня в файле node.cpp

template <typename PublisherMsgType, typename SubscriberMsgType>
Node<PublisherMsgType, SubscriberMsgType>::Node(int sizeMessageBuffer,
                                                char* publisherTopicName,
                                                char* subscriberTopicName):
    mPublisher(mNodeHandler.advertise<PublisherMsgType>(publisherTopicName, sizeMessageBuffer)),
    mSubscriber(mNodeHandler.subscribe(subscriberTopicName,
                                       sizeMessageBuffer,
                                       &Node<PublisherMsgType, SubscriberMsgType>::mCallbackFunc,
                                       this))
{

}

А на счёт не прилинковал не знаю. В CMakeList.txt всё чётко указано, вроде.

set(BAL_SOURCES
    src/positions.cpp
    src/node.cpp
    src/life_node.cpp
)

add_executable(johnny_life
    ${BAL_SOURCES}
)

looogle
() автор топика

Во-первых, шаблонные классы (в твоём случае это Node) разбить на объявление (.h) и реализацию (.cpp) не выйдет. По этому код из node.cpp переноси в node.h (самое простое решение).

Если хочешь красивее — погугли как люди обычно делают шаблонные классы.

Во-вторых, почитай какую-нибудь литературу о том, как работают шаблонные классы (в частности как они генерируются и взаимоотносятся).

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 2)
Ответ на: комментарий от KennyMinigun

Во-первых, шаблонные классы (в твоём случае это Node) разбить на объявление (.h) и реализацию (.cpp) не выйдет. По этому код из node.cpp переноси в node.h (самое простое решение).

На самом деле можно разбивать, но для этого нужно в cpp определить все возможные специализации шаблонов, для которых нужно сгенерить код. Но такое далеко не всегда возможно сделать красиво.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)

А я просто посоветую вместо тега [code] использовать [code=c++], так читать приятнее все-таки.

CrossFire ★★★★★
()
Ответ на: комментарий от four_str_sam

Понял, всем спасибо. Буду учиться.

P.S. А hpp файлы случайно не для того придумали, чтобы совмещать реализацию и объявление в таких вот случаях?

looogle
() автор топика
Ответ на: комментарий от CrossFire

А я просто посоветую вместо тега [code] использовать [code=c++], так читать приятнее все-таки.

Я вроде как и использовал. В комментарии он нормально подсветку сделал, а в посте — нет.

looogle
() автор топика
Ответ на: комментарий от looogle

Нет, под .hpp подразумевается любой хедер для С++. Что бы не путать с хедерами С

four_str_sam
()
Ответ на: комментарий от looogle

Я вроде как и использовал. В комментарии он нормально подсветку сделал, а в посте — нет.

Может коварная 'c' оказалась русской?

CrossFire ★★★★★
()
Ответ на: комментарий от looogle

Да какая разница, как назвать хедер? Хоть *.chlenpp, include все равно отработает

DELIRIUM ☆☆☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.