**这些普罗米修斯C++代码里面的双冒号::到底代表着什么,有必要真正弄清楚了(基本是命名空间)很多彻底弄清楚了!

A::B   c A是命名空间,B是命名空间A中的类    c是类B对应的实例化对象    
A::B() A是命名空间,B是命名空间中的一个独立的函数,不属于哪个类。 如ros::init()  
A.B A是一个类的实例化对象,B是这个对象里面的一个属性,或者理解为类里面的一个变量    
A.B() A是一个类的实例化对象,B是这个对象里面的一个函数    
A.B.C B是A的类里面一个类成员变量,C是B这种类里面的一个成员变量。

geometry_msgs::Pose pose

pose.position.x

感觉似乎pose类是position类和orientation类的合集,也就是一个大消息是两个小消息的合集,这种类叫什么?一个类继承了两个类这种岂不是叫接口?不是,C++可以多重继承。

 
A.B.C.D 同A.B.C

geometry_msgs::PoseStamped A

A.pose.position.x

 
A::B().C() A是命名空间,意思等同于A::B();A::C();
ros::Duration(3.0).sleep()
《C++ primer》247面有说
A.B::C() ::起到作用域分辨符的作用    
A::B::C

A和B可能是嵌套的命名空间

还有一种情况,B是A类型里面的枚举类型,枚举类型作为类的成员变量是静态成员变量。(ROS话题消息里面这样写就是这种情况!)

prometheus_msgs::ControlCommand::Move  

我在C++ primer里还看到过  A.B::C

拍自《C++ primer》549面

https://www.cnblogs.com/dishengAndziyu/p/10916298.html

拍自《C++ primer》247面

============================================================================================================

我看了下双冒号的作用无非是两种,一种是作用域(命名空间),一种是静态类。

拍自《C++ primer》147面

我下面这篇博文也有讲,一般是命名空间。Eigen  ros  std应该都是命名空间。

很多为了防止不同类里面有相同的函数名称,或者成员名称(就是变量名称嘛,因为类里面包含变量和函数啊,下面Eigen::Vector3d应该不是函数是变量,应该是类名称,然后创建对象)(是的,应该基本都是命名空间,防止重名的出现,确实工程大了之后。你还调用各种库,确实有这种风险)

下面那样写是在创建对象https://www.jianshu.com/p/79bc4ff1a8f8?utm_source=desktop&utm_medium=timeline

就是Eigen::Vector3d pos_drone_mocap; //无人机当前位置 (vicon)  这种写法是在创建对象,而不是一个变量。我是说不对劲,就算是变量也是通过类来引用啊。

《ROS机器人编程原理与应用》这本书里面也明确说了

https://www.cnblogs.com/kimmychul/p/3951229.html

https://blog.csdn.net/sinat_16643223/article/details/107620182

https://github.com/maxibooksiyi/Prometheus/blob/pr-experiment-TX2/Modules/control/src/px4_pos_estimator.cpp

这种我已经多次看到

https://blog.csdn.net/yxpandjay/article/details/80587916

https://www.xuebuyuan.com/2175603.html

https://blog.csdn.net/yaodaoji/article/details/107857790

https://blog.csdn.net/sn_gis/article/details/79009006

可能就是普罗米修斯代码里面没有写using namespace Eigen,所以都带着Eigen::

https://blog.csdn.net/guijiaqing/article/details/106235957

普罗米修斯自身代码里面也有这么写。

https://github.com/maxibooksiyi/Prometheus/blob/pr-experiment-TX2/Modules/mission/autonomous_landing/autonomous_landing_gps_new.cpp

https://blog.csdn.net/weixin_40603219/article/details/88596642

《机器人操作系统入门必备  机器人编程一学就会》这里面也专门在C++基础知识里面说了C++中的命名空间,用了双冒号。估计ROS中大部分的双冒号都是命名空间。

这种用法我知道为什么了,看来还是C++的命名空间的基础知识没有掌握好。

https://blog.csdn.net/sn_gis/article/details/79009006

https://www.cnblogs.com/wanghuixi/p/6887390.html

那我现在又有个疑问了,像 ROS的命名空间原本是在哪里写或者定义的呢。这里用的时候直接写ros::就可以,那它最开始是在哪里定义好的呢。也就是它那命名空间是在哪里声明的。

似乎声明是要像下面这样声明,可能他们在写对应的库的时候已经这么写了,比如Eigen库写的时候可能就已经这么写了这么定义了。

https://www.runoob.com/cplusplus/cpp-namespaces.html

怪不得写了using namespace std就没有再写什么using namespace Eigen或者using namespace ros了,在我上面给出的普罗米修斯代码里面。

https://blog.csdn.net/sinat_16643223/article/details/107662464

真的是一点点啃透普罗米修斯的同时也一点点补充着C++和ROS。

现在再看普罗米修斯代码里的这些东西,应该就不会乱了。清楚是创建对象。

https://gitee.com/maxibooksiyi/Prometheus/blob/master/Modules/control/src/px4_sender.cpp

这种是不是创建对象的时候同时调用了构造函数

https://gitee.com/maxibooksiyi/Prometheus/blob/master/Modules/control/src/px4_sender.cpp

那ros::init()

ros::spin()

ros::ok()

这种该怎么理解,这些都是ros的基础代码里面用到的,当然普罗米修斯也用到了,这是直接调用一个明明空间下的函数?不应该是先调用类么?

所以ros到底是一个作用域还是一个类名?

Eigen也有这种用法,Eigen在这里讲道理是命名空间,双冒号后面跟了个函数。

我发现下面不就是命名空间::函数么,这么用说明函数直接写在了命名空间下面没有写在类下面,是不是这个意思?所以ros::init()  ros::spin()  ros::ok()这几个函数不是写在类里面的,我暂时这么理解吧。

看这篇博文  https://blog.csdn.net/sinat_16643223/article/details/114535835   

init()应该是一个单独的函数

这种的又怎么理解

https://gitee.com/maxibooksiyi/Prometheus/blob/master/Modules/control/src/px4_sender.cpp

这种三个的我怀疑,第一个是命名空间,第二个是类名,第三个是类中的成员变量名。为什么可以直接这么用,而不用创建对象?

Eigen也是有这样用的,连着三个。

下面拍自《ROS机器人编程原理与应用》157面。

但我总感觉这个不是命名空间,这个普罗米修斯的消息是我们自己定义的,实际内容是那样的,没有看到什么定义命名空间啊。

还是说ROS中的消息就是这么用的?是的,和ROS中其他消息的用法一样  https://www.jianshu.com/p/5c75c24f0fe6

我感觉他们命名空间的名称很多时候和所在功能包名称一样,比如std_msgs。

prometheus_msgs::ControlCommand和 geometry_msgs::PoseStamped性质应该是一样的

我感觉他们命名空间的名称很多时候和所在功能包名称一样,比如std_msgs。是否一个节点或者功能包是有自己默认的命名空间的在ROS里面?

https://www.jianshu.com/p/3ed51b015223

prometheus_msgs::ControlCommand和 geometry_msgs::PoseStamped性质应该是一样的

https://gitee.com/maxibooksiyi/Prometheus/blob/master/Modules/control/src/px4_sender.cpp

https://gitee.com/maxibooksiyi/Prometheus/blob/master/Modules/common/msgs/msg/ControlCommand.msg

有一个重大发现,似乎证明了我上面的猜想

https://blog.csdn.net/cookie909/article/details/79842334

这里也说私有名称是用他们节点名称作为命名空间

https://www.cnblogs.com/zjiaxing/p/5541841.html

莫非话题名称前有个斜杠也是因为命名空间!!!!!!!!!!!

https://blog.csdn.net/lielieyu/article/details/79594734?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=1328602.58322.16151868030891917&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

libo说这本质是一个值,是命名空间下的命名空间下的一个变量,这么理解的。嵌套的命名空间。

https://blog.csdn.net/weixin_38956024/article/details/112131277

但是上面如果理解成命名空间的嵌套,那下面这就不好理解了啊,我感觉他们本质还是一个类啊,命名空间下的一个类啊。不然怎么创建对象呢。是不是msg文件自动生成类???但是类里面的变量为什么不需要创建对象再去引用呢。

https://gitee.com/maxibooksiyi/Prometheus/blob/master/Modules/control/src/px4_sender.cpp

你看这些消息的用法,似乎都是一个类。

他们自定义的msg也是这么用,可能ROS话题消息都是这么用?包名::消息名    对象名

https://blog.csdn.net/u013453604/article/details/72903398

https://blog.csdn.net/sinat_16643223/article/details/114537318

书上讲自定义消息类型的时候也这么说了,在《ROS机器人编程原理与应用》36面。

可能因为消息里面那几个量的值是定的,跟创建对象没有关系,所以可以直接这么写?那我现在明白为什么静态类可以直接写类名了,确实你不创建对象,那几个量的值都是确定的!!!!!!我对这个理解更进一步了

下面拍自《ROS机器人开发实践》44面

https://blog.csdn.net/weixin_40539125/article/details/84112472

https://blog.csdn.net/sinat_16643223/article/details/114539707

我在《ROS机器人编程原理与应用》这本书里面也看到普罗米修斯里面这种A::B::C这种用法了,看来普罗米修斯里面这样写不是个例,可能真的大家都是这么写的。

看了下那几个变量确实已经给值了

https://github.com/ros/common_msgs/blob/noetic-devel/visualization_msgs/msg/InteractiveMarkerControl.msg

我去看了下普罗米修斯的ControlCOmmand.msg对应的头文件里面,那几个给了值的量,是放在枚举里面。是不是因为是枚举类型所以这么写?写为A::B::C,我搜了下还真的是,枚举类型作为类的成员变量的时候是静态成员变量!!!!!!!!!!我们这种深入本质深入源码去找才真正彻底弄清楚为什么这么写,我原本是猜测它自动生成头文件时那些赋值的变量前面自动加上typedef或者static什么的,刚刚有这种想法所以重启电脑进入Ubuntu看,虽然不是那样但确实是自动生成头文件改了些东西,所以用的时候只能那么写!!!!!!!!

ControlCommand.h

// Generated by gencpp from file prometheus_msgs/ControlCommand.msg
// DO NOT EDIT!


#ifndef PROMETHEUS_MSGS_MESSAGE_CONTROLCOMMAND_H
#define PROMETHEUS_MSGS_MESSAGE_CONTROLCOMMAND_H


#include <string>
#include <vector>
#include <map>

#include <ros/types.h>
#include <ros/serialization.h>
#include <ros/builtin_message_traits.h>
#include <ros/message_operations.h>

#include <std_msgs/Header.h>
#include <prometheus_msgs/PositionReference.h>

namespace prometheus_msgs
{
template <class ContainerAllocator>
struct ControlCommand_
{
  typedef ControlCommand_<ContainerAllocator> Type;

  ControlCommand_()
    : header()
    , Command_ID(0)
    , source()
    , Mode(0)
    , Reference_State()  {
    }
  ControlCommand_(const ContainerAllocator& _alloc)
    : header(_alloc)
    , Command_ID(0)
    , source(_alloc)
    , Mode(0)
    , Reference_State(_alloc)  {
  (void)_alloc;
    }



   typedef  ::std_msgs::Header_<ContainerAllocator>  _header_type;
  _header_type header;

   typedef uint32_t _Command_ID_type;
  _Command_ID_type Command_ID;

   typedef std::basic_string<char, std::char_traits<char>, typename ContainerAllocator::template rebind<char>::other >  _source_type;
  _source_type source;

   typedef uint8_t _Mode_type;
  _Mode_type Mode;

   typedef  ::prometheus_msgs::PositionReference_<ContainerAllocator>  _Reference_State_type;
  _Reference_State_type Reference_State;



// reducing the odds to have name collisions with Windows.h 
#if defined(_WIN32) && defined(Idle)
  #undef Idle
#endif
#if defined(_WIN32) && defined(Takeoff)
  #undef Takeoff
#endif
#if defined(_WIN32) && defined(Hold)
  #undef Hold
#endif
#if defined(_WIN32) && defined(Land)
  #undef Land
#endif
#if defined(_WIN32) && defined(Move)
  #undef Move
#endif
#if defined(_WIN32) && defined(Disarm)
  #undef Disarm
#endif
#if defined(_WIN32) && defined(User_Mode1)
  #undef User_Mode1
#endif
#if defined(_WIN32) && defined(User_Mode2)
  #undef User_Mode2
#endif

  enum {
    Idle = 0u,
    Takeoff = 1u,
    Hold = 2u,
    Land = 3u,
    Move = 4u,
    Disarm = 5u,
    User_Mode1 = 6u,
    User_Mode2 = 7u,
  };


  typedef boost::shared_ptr< ::prometheus_msgs::ControlCommand_<ContainerAllocator> > Ptr;
  typedef boost::shared_ptr< ::prometheus_msgs::ControlCommand_<ContainerAllocator> const> ConstPtr;

}; // struct ControlCommand_

typedef ::prometheus_msgs::ControlCommand_<std::allocator<void> > ControlCommand;

typedef boost::shared_ptr< ::prometheus_msgs::ControlCommand > ControlCommandPtr;
typedef boost::shared_ptr< ::prometheus_msgs::ControlCommand const> ControlCommandConstPtr;

// constants requiring out of line definition

   

   

   

   

   

   

   

   



template<typename ContainerAllocator>
std::ostream& operator<<(std::ostream& s, const ::prometheus_msgs::ControlCommand_<ContainerAllocator> & v)
{
ros::message_operations::Printer< ::prometheus_msgs::ControlCommand_<ContainerAllocator> >::stream(s, "", v);
return s;
}


template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator==(const ::prometheus_msgs::ControlCommand_<ContainerAllocator1> & lhs, const ::prometheus_msgs::ControlCommand_<ContainerAllocator2> & rhs)
{
  return lhs.header == rhs.header &&
    lhs.Command_ID == rhs.Command_ID &&
    lhs.source == rhs.source &&
    lhs.Mode == rhs.Mode &&
    lhs.Reference_State == rhs.Reference_State;
}

template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator!=(const ::prometheus_msgs::ControlCommand_<ContainerAllocator1> & lhs, const ::prometheus_msgs::ControlCommand_<ContainerAllocator2> & rhs)
{
  return !(lhs == rhs);
}


} // namespace prometheus_msgs

namespace ros
{
namespace message_traits
{





template <class ContainerAllocator>
struct IsFixedSize< ::prometheus_msgs::ControlCommand_<ContainerAllocator> >
  : FalseType
  { };

template <class ContainerAllocator>
struct IsFixedSize< ::prometheus_msgs::ControlCommand_<ContainerAllocator> const>
  : FalseType
  { };

template <class ContainerAllocator>
struct IsMessage< ::prometheus_msgs::ControlCommand_<ContainerAllocator> >
  : TrueType
  { };

template <class ContainerAllocator>
struct IsMessage< ::prometheus_msgs::ControlCommand_<ContainerAllocator> const>
  : TrueType
  { };

template <class ContainerAllocator>
struct HasHeader< ::prometheus_msgs::ControlCommand_<ContainerAllocator> >
  : TrueType
  { };

template <class ContainerAllocator>
struct HasHeader< ::prometheus_msgs::ControlCommand_<ContainerAllocator> const>
  : TrueType
  { };


template<class ContainerAllocator>
struct MD5Sum< ::prometheus_msgs::ControlCommand_<ContainerAllocator> >
{
  static const char* value()
  {
    return "452e60a420203d6b2f7bcba6708b37bc";
  }

  static const char* value(const ::prometheus_msgs::ControlCommand_<ContainerAllocator>&) { return value(); }
  static const uint64_t static_value1 = 0x452e60a420203d6bULL;
  static const uint64_t static_value2 = 0x2f7bcba6708b37bcULL;
};

template<class ContainerAllocator>
struct DataType< ::prometheus_msgs::ControlCommand_<ContainerAllocator> >
{
  static const char* value()
  {
    return "prometheus_msgs/ControlCommand";
  }

  static const char* value(const ::prometheus_msgs::ControlCommand_<ContainerAllocator>&) { return value(); }
};

template<class ContainerAllocator>
struct Definition< ::prometheus_msgs::ControlCommand_<ContainerAllocator> >
{
  static const char* value()
  {
    return "std_msgs/Header header\n"
"\n"
"## 控制命令的编号 防止接收到错误命令, 编号应该逐次递加\n"
"uint32 Command_ID\n"
"\n"
"## 消息来源\n"
"string source\n"
"## 控制命令的模式 \n"
"uint8 Mode\n"
"# enum Mode 控制模式枚举\n"
"uint8 Idle=0\n"
"uint8 Takeoff=1\n"
"uint8 Hold=2\n"
"uint8 Land=3\n"
"uint8 Move=4\n"
"uint8 Disarm=5\n"
"uint8 User_Mode1=6\n"
"uint8 User_Mode2=7\n"
"\n"
"## 控制参考量 \n"
"## 位置参考量:位置、速度、加速度、加加速度、加加加速度\n"
"## 角度参考量:偏航角、偏航角速度、偏航角加速度\n"
"PositionReference Reference_State\n"
"\n"
"================================================================================\n"
"MSG: std_msgs/Header\n"
"# Standard metadata for higher-level stamped data types.\n"
"# This is generally used to communicate timestamped data \n"
"# in a particular coordinate frame.\n"
"# \n"
"# sequence ID: consecutively increasing ID \n"
"uint32 seq\n"
"#Two-integer timestamp that is expressed as:\n"
"# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')\n"
"# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')\n"
"# time-handling sugar is provided by the client library\n"
"time stamp\n"
"#Frame this data is associated with\n"
"string frame_id\n"
"\n"
"================================================================================\n"
"MSG: prometheus_msgs/PositionReference\n"
"std_msgs/Header header\n"
"\n"
"## 位置控制参考量\n"
"\n"
"## 默认为 XYZ位置追踪模式 (sub_mode = 0); 速度追踪启用时,控制器不考虑位置参考量及位置状态反馈\n"
"uint8 Move_mode\n"
"\n"
"uint8 XYZ_POS      = 0  ##0b00\n"
"uint8 XY_POS_Z_VEL = 1  ##0b01\n"
"uint8 XY_VEL_Z_POS = 2  ##0b10\n"
"uint8 XYZ_VEL = 3       ##0b11\n"
"uint8 XYZ_ACC = 4\n"
"uint8 TRAJECTORY   = 5  \n"
"\n"
"uint8 Move_frame\n"
"# 默认情况下均为ENU_FRAME,注意轨迹追踪和XYZ_ACC一定是ENU_FRAME\n"
"uint8 ENU_FRAME  = 0\n"
"uint8 BODY_FRAME = 1\n"
"uint8 MIX_FRAME = 2 ##2020.4.6 临时增加的模式,后期需要统一整合,该模式下,xy采用机体系控制,z采用enu系控制\n"
"\n"
"## 时刻: 用于轨迹追踪\n"
"float32 time_from_start          ## [s]\n"
"\n"
"## 参考量:位置、速度、加速度、加加速度、加加加速度\n"
"float32[3] position_ref          ## [m]\n"
"float32[3] velocity_ref          ## [m/s]\n"
"float32[3] acceleration_ref      ## [m/s^2]\n"
"## float32[3] jerk_ref              ## [m/s^3]\n"
"## float32[3] snap_ref              ## [m/s^4]\n"
"\n"
"## 角度参考量:偏航角、偏航角速度、偏航角加速度\n"
"float32 yaw_ref                  ## [rad]\n"
"## float32 yaw_rate_ref             ## [rad/s] \n"
"## float32 yaw_acceleration_ref     ## [rad/s] \n"
;
  }

  static const char* value(const ::prometheus_msgs::ControlCommand_<ContainerAllocator>&) { return value(); }
};

} // namespace message_traits
} // namespace ros

namespace ros
{
namespace serialization
{

  template<class ContainerAllocator> struct Serializer< ::prometheus_msgs::ControlCommand_<ContainerAllocator> >
  {
    template<typename Stream, typename T> inline static void allInOne(Stream& stream, T m)
    {
      stream.next(m.header);
      stream.next(m.Command_ID);
      stream.next(m.source);
      stream.next(m.Mode);
      stream.next(m.Reference_State);
    }

    ROS_DECLARE_ALLINONE_SERIALIZER
  }; // struct ControlCommand_

} // namespace serialization
} // namespace ros

namespace ros
{
namespace message_operations
{

template<class ContainerAllocator>
struct Printer< ::prometheus_msgs::ControlCommand_<ContainerAllocator> >
{
  template<typename Stream> static void stream(Stream& s, const std::string& indent, const ::prometheus_msgs::ControlCommand_<ContainerAllocator>& v)
  {
    s << indent << "header: ";
    s << std::endl;
    Printer< ::std_msgs::Header_<ContainerAllocator> >::stream(s, indent + "  ", v.header);
    s << indent << "Command_ID: ";
    Printer<uint32_t>::stream(s, indent + "  ", v.Command_ID);
    s << indent << "source: ";
    Printer<std::basic_string<char, std::char_traits<char>, typename ContainerAllocator::template rebind<char>::other > >::stream(s, indent + "  ", v.source);
    s << indent << "Mode: ";
    Printer<uint8_t>::stream(s, indent + "  ", v.Mode);
    s << indent << "Reference_State: ";
    s << std::endl;
    Printer< ::prometheus_msgs::PositionReference_<ContainerAllocator> >::stream(s, indent + "  ", v.Reference_State);
  }
};

} // namespace message_operations
} // namespace ros

#endif // PROMETHEUS_MSGS_MESSAGE_CONTROLCOMMAND_H

https://blog.csdn.net/bbjjqq/article/details/6079289

那么现在应该是可以真正非常彻底地啃透普罗米修斯里面比如 px4_pos_estimate.cpp的代码了。

我希望你去啃Tensorflow的代码也像这样去啃。

https://gitee.com/maxibooksiyi/Prometheus/blob/master/Modules/control/src/px4_sender.cpp

上面那个那样写确实就是命名空间下一个独立的函数,没有被类包含的,看来我的推测是对的。我在普罗米修斯代码里面找了下,确实就是这样。所以可以推测 ros::init()  ros::ok()  ros::spin()这种应该也是同样的情况!!!!!!!!!

《ROS机器人开发实践》里面有写ROS中的命名空间

总结好了之后,再去看opencv的代码都会好得多。

现在可以完全确定引用(我知创建实例化对象的时候,不是那种静态值直接用的,当然静态值直接用最前面那个也是命名空间,那就都一样吧,都是命名空间)ROS话题消息::最前面那个就是命名空间!!!!!

https://blog.csdn.net/sinat_16643223/article/details/114730336

所以以后再看到双冒号,最前面那个就是命名空间!!!!!几乎不用犹豫什么。

那分析一下这种情况怎么理解。

现在来分析一下这种情况,结合这篇博文: https://blog.csdn.net/sinat_16643223/article/details/114730336

讲道理一个消息就是一种类,你包含了其他的消息就是包含了其他的类啊,

所以你看pose这个消息的头文件里面是include了的poin和quaternion这两个消息的头文件的

上面写的struct似乎也是定义类的。

这应该就是一个函数。这应该是多重继承的写法

http://m.biancheng.net/view/2277.html

这也应该是继承的写法。

我想起java是不能多重继承的,得用接口,是不是C++可以多重继承。

而且我刚刚发现上面正是多重继承下的构造函数!!!!!Pose_()正是构造函数!!!!!

http://m.biancheng.net/view/2277.html

所以ROS里面一个消息类型是由其他小消息类型组合而成的,在C++层面上是通过多重继承实现的。

那这种A.B.C的写法是不是属于子类调用或者访问父类成员变量,B是父类。

我现在有点怀疑是不是结构体嵌套。虽然C++中结构体和类没那么大区分,但是通过结构体嵌套的概念比较好解释,不然为什么它不写成类?当然我再C++ primer里面也看到有类嵌套。

https://blog.csdn.net/sinat_16643223/article/details/114765223

https://www.cnblogs.com/lanhaicode/p/10312032.html

https://blog.csdn.net/JoeBlackzqq/article/details/7098329

那这种写法其实就是说Pose_这个结构体继承了 Message这个结构体,按照上面的,继承结构体时也是写的Public!!!

https://blog.csdn.net/sinat_16643223/article/details/114730336

或许关键是这两句,相当于一个类里面有两个其他类成员变量。这算不算嵌套类?是啊,一个类里面的成员变量就是一个类的实例化对象,这种情况怎么弄。这应该是很常见的情况啊是不是。这不是嵌套类,嵌套类是一个类定义在另一个类的内部(《C++ primer》746面),这不是,这应该就是普通的情况。

似乎叫类类型,《C++ primer》有说到类类型,这种是不是就叫类类型,类里面有个类类型成员?甚至类类型成员里面还有类类型成员,这么一层层包着。

https://blog.csdn.net/shengwenj/article/details/49337223

我们可以再来验证一下,这种是不是也是类中有类成员。

可以看到这个Command_Now也是一个话题消息类型的实例化对象。

你看,在ContrilCommand.msg里面它就直接写了一个

PositionReference Reference_State

就是一个类类型的成员变量不是!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

https://gitee.com/maxibooksiyi/Prometheus/blob/master/Modules/common/msgs/msg/ControlCommand.msg

https://gitee.com/maxibooksiyi/Prometheus/blob/master/Modules/common/msgs/msg/PositionReference.msg

也怪不得PoseStamped话题消息类型定义里面就两句话,我一开始还以为是不是弄错了,现在觉得没有,就是两个类类型成员变量!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!那这样我的理解是对的。

https://github.com/ros/common_msgs/blob/noetic-devel/geometry_msgs/msg/PoseStamped.msg

那么现在看这个也应该好理解了,为什么是A.B.C.D对吧,这么多点。

拍自《ROS机器人编程原理与应用》330面

https://blog.csdn.net/sinat_16643223/article/details/114542703

猜你喜欢

转载自blog.csdn.net/sinat_16643223/article/details/114503233