【问题标题】:Refer to a function that is member of a class [closed]引用作为类成员的函数[关闭]
【发布时间】:2017-07-14 12:57:37
【问题描述】:

所以我有这个意大利面条代码项目,我正在尝试使其面向对象。不幸的是,我遇到了我不太理解的错误,所以我尝试创建会引发相同错误而不会引发相同错误的简约代码。


下面是一些可以编译的简约代码:

(名为“ims.cpp”的文件)

#include <cstdio>

#include <ros/ros.h>

#include <visualization_msgs/Marker.h>
#include <visualization_msgs/InteractiveMarker.h>
#include <interactive_markers/interactive_marker_server.h>
#include <interactive_markers/menu_handler.h>

#include <rosbag/bag.h>
#include <rosbag/view.h>
#include <ros/param.h>

#include <fstream>
#include <cmath>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>

using namespace visualization_msgs;
using namespace geometry_msgs;
using namespace std;
using namespace boost;

boost::shared_ptr<interactive_markers::InteractiveMarkerServer> server;

void doNothing(const InteractiveMarkerFeedbackConstPtr &feedback){
}

void testServer(){

  InteractiveMarker inter_marker;
  inter_marker.header.frame_id = 1;
  Point pos;
  pos.x = 3;
  pos.y = 3;
  inter_marker.pose.position = pos;
  inter_marker.scale = 2;
  inter_marker.name = "testServer";

  server->insert(inter_marker, &doNothing);
}

int main(){}

解释:这是一个 ROS(机器人操作系统)项目,我仍然相信这是一个一般的 c++ 问题,所以我没有在他们的“ros::answers”论坛上问这个问题。请不要被类型混淆,我们会解决问题的。

函数“interactive_markers::InteractiveMarkerServer.insert”需要一个“visualization_msgs::InteractiveMarker &”和一个具有“InteractiveMarkerFeedbackConstPtr &”类型参数的函数,如提供的那样。 见:http://docs.ros.org/jade/api/interactive_markers /html/classinteractive__markers_1_1InteractiveMarkerServer.html


所以抛出我的错误的最小代码将是一个在“doNothing”函数中根本没有所需参数的代码,如下所示:

(名为“ims.cpp”的文件)

#include <as above>

using namespace visualization_msgs;
using namespace geometry_msgs;
using namespace std;
using namespace boost;

boost::shared_ptr<interactive_markers::InteractiveMarkerServer> server;

void doNothing(){
}

void testServer(){

  InteractiveMarker inter_marker;
  inter_marker.header.frame_id = 1;
  Point pos;
  pos.x = 3;
  pos.y = 3;
  inter_marker.pose.position = pos;
  inter_marker.scale = 2;
  inter_marker.name = "testServer";

  server->insert(inter_marker, &doNothing);
}

int main(){}

抛出错误:

    In file included from /usr/include/boost/function/detail/maybe_include.hpp:18:0,
                 from /usr/include/boost/function/detail/function_iterate.hpp:14,
                 from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52,
                 from /usr/include/boost/function.hpp:64,
                 from /opt/ros/indigo/include/ros/forwards.h:40,
                 from /opt/ros/indigo/include/ros/common.h:37,
                 from /opt/ros/indigo/include/ros/ros.h:43,
                 from /home/ros/ros/src/robotrainer_editor/heika_beta/ims/src/ims.cpp:3:
/usr/include/boost/function/function_template.hpp: In instantiation of ‘static void boost::detail::function::void_function_invoker1<FunctionPtr, R, T0>::invoke(boost::detail::function::function_buffer&, T0) [with FunctionPtr = void (*)(); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&]’:
/usr/include/boost/function/function_template.hpp:934:38:   required from ‘void boost::function1<R, T1>::assign_to(Functor) [with Functor = void (*)(); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&]’
/usr/include/boost/function/function_template.hpp:722:7:   required from ‘boost::function1<R, T1>::function1(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = void (*)(); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/include/boost/function/function_template.hpp:1069:16:   required from ‘boost::function<R(T0)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = void (*)(); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/home/ros/ros/src/robotrainer_editor/heika_beta/ims/src/ims.cpp:40:42:   required from here
/usr/include/boost/function/function_template.hpp:112:11: error: too many arguments to function
           BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));

这是有道理的,对吧?该函数没有所需的参数,因此编译器会抱怨。


所以现在我们解决了真正的问题:在面向对象的代码中,我遇到了同样的问题:

头文件

(名为“ims.h”的文件)

#include <cstdio>

#include <ros/ros.h>

#include <visualization_msgs/Marker.h>
#include <visualization_msgs/InteractiveMarker.h>
#include <interactive_markers/interactive_marker_server.h>
#include <interactive_markers/menu_handler.h>

#include <rosbag/bag.h>
#include <rosbag/view.h>
#include <ros/param.h>

#include <fstream>
#include <cmath>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>

using namespace visualization_msgs;
using namespace geometry_msgs;
using namespace std;
using namespace boost;

class IMS{

  boost::shared_ptr<interactive_markers::InteractiveMarkerServer> server;

  IMS();

  void doNothing(const InteractiveMarkerFeedbackConstPtr &feedback);

  void testServer();

  int main();

};

CPP 声明

(名为“ims.cpp”的文件)

#include <ims.h>

IMS::IMS(){}

void IMS::doNothing(const InteractiveMarkerFeedbackConstPtr &feedback){
}

void IMS::testServer(){

  InteractiveMarker inter_marker;
  inter_marker.header.frame_id = 1;
  Point pos;
  pos.x = 3;
  pos.y = 3;
  inter_marker.pose.position = pos;
  inter_marker.scale = 2;
  inter_marker.name = "testServer";

  server->insert(inter_marker, &IMS::doNothing); //other options that didn't work either: doNothing);//*this->doNothing(const InteractiveMarkerFeedbackConstPtr &feedback));//*this->doNothing());//this->doNothing);//&this->doNothing);//&IMS::doNothing);//&doNothing);
}

int IMS::main(){}

抛出错误:

In file included from /usr/include/boost/function/detail/maybe_include.hpp:18:0,
                 from /usr/include/boost/function/detail/function_iterate.hpp:14,
                 from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52,
                 from /usr/include/boost/function.hpp:64,
                 from /opt/ros/indigo/include/ros/forwards.h:40,
                 from /opt/ros/indigo/include/ros/common.h:37,
                 from /opt/ros/indigo/include/ros/ros.h:43,
                 from /home/ros/ros/src/robotrainer_editor/heika_beta/ims/include/ims.h:3,
                 from /home/ros/ros/src/robotrainer_editor/heika_beta/ims/src/ims.cpp:1:
/usr/include/boost/function/function_template.hpp: In instantiation of ‘static void boost::detail::function::function_void_mem_invoker1<MemberPtr, R, T0>::invoke(boost::detail::function::function_buffer&, T0) [with MemberPtr = void (IMS::*)(const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&]’:
/usr/include/boost/function/function_template.hpp:934:38:   required from ‘void boost::function1<R, T1>::assign_to(Functor) [with Functor = void (IMS::*)(const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&]’
/usr/include/boost/function/function_template.hpp:722:7:   required from ‘boost::function1<R, T1>::function1(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = void (IMS::*)(const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/include/boost/function/function_template.hpp:1069:16:   required from ‘boost::function<R(T0)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = void (IMS::*)(const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/home/ros/ros/src/robotrainer_editor/heika_beta/ims/src/ims.cpp:19:47:   required from here
/usr/include/boost/function/function_template.hpp:225:11: error: no match for call to ‘(boost::_mfi::mf1<void, IMS, const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&>) (const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&)’
           BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));

诊断:

我的一个朋友实际上已经诊断出问题的合理来源:显然编译器将代码重新格式化为这个

void IMS::doNothing(IMS this, const InteractiveMarkerFeedbackConstPtr &feedback){

这当然会导致错误,因为参数不再符合我们的期望。


这是我的要求:

这个诊断正确吗?

如果是:是否可以解决?如何解决?

else:真正的问题是什么?

感谢所有阅读此长主题的人,并提前感谢您的回答!


解决方案(根据“einpoklum”的建议)

最适合我的概念的解决方案是 lambda,它创建一个函数来包装恶意的“this”参数。

std::function 什么都没有 = [this] (const InteractiveMarkerFeedbackConstPtr &feedback) {this->doNothing(feedback);};

server->insert(inter_marker, nothing);

感谢您和所有费心阅读整个帖子的人,对于我难以理解地提出问题感到抱歉。

【问题讨论】:

  • doNothing 应该是static,(在类定义中是static void doNothing(const InteractiveMarkerFeedbackConstPtr &amp;feedback);)。 static 函数没有 this
  • @Kelvin Sherlock 然后会发生的一个问题是(真正的)函数(真正的项目,做某事的函数)实际上使用类属性,它当时不能,可以吗?还有其他方法吗?

标签: c++ pointers lambda types pass-by-reference


【解决方案1】:

试图穿过大量文本并冒险回答:我认为(但不确定)问题是您试图将(非静态)成员函数传递为虽然它是一个独立的功能。

这应该行不通,因为你不能“像那样”调用成员函数——它必须有一个关联的对象。在实现层面上,需要使用类实例的地址来调用那段代码,以充当this 对象。

在这些情况下你可以做的是:

  • 使用std::mem_fn 包装您的成员函数以获得正确的函数,其中额外的第一个参数是实例,或者
  • 使用 lambda 以某种方式实例化对象(或仅将实例作为引用)并调用该实例的方法。 lambda 本身将退化为一个独立的函数,您可以传递其指针。
  • 创建方法static - 如果它实际上不使用任何特定于实例的数据。

【讨论】:

  • 你是我的英雄! std::function&lt;void(const InteractiveMarkerFeedbackConstPtr &amp;)&gt; nothing = [this] (const InteractiveMarkerFeedbackConstPtr &amp;feedback) {this-&gt;doNothing(feedback);};server-&gt;insert(inter_marker, &amp;IMS::doNothing);
  • @GDawg: 1. 如果您认为该解决方案有帮助,请考虑点赞。 2. 没有“e”的“hero” :-) 3. 阅读你的问题非常困难,你真的应该付出更多的努力来提供 minimal 我们可以自己编译的例子走着瞧吧。 4.您在此处列出的两个语句是不相关的,即第二个不使用您定义的 lambda;也许你抄错了?
  • sry,upvote 暂停,stack-overflow 的新手。以及关于最小代码:对不起,我没有找到任何具有相同问题的标准 c++ 方法^^ 来测试你在我的特定版本中安装 ros 所需的代码等等,只是希望有人理解理论概念,你做到了!服务器->插入(inter_marker,什么都没有); *英雄
猜你喜欢
  • 2018-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-15
  • 1970-01-01
  • 1970-01-01
  • 2013-03-08
相关资源
最近更新 更多