为什么在指向对象的指针上调用方法与在对象本身上调用方法有不同的行为?

时间:2012-08-16 12:27:54

标签: c++ pointers

我有一些代码,我有一个指向对象的指针。我在该指针上调用一个方法,但在这种情况下该方法的行为是错误的。我尝试在对象本身上调用一个方法,这实际上给出了方法所需的行为。

为什么这会导致不同的行为?

还有一种方法可以在不使用指针的情况下将对象分配给新变量,因为我希望在对象本身上调用该方法的行为吗?

感谢。

编辑:

希望是一个充分的例子:

在Robot类中:

std::vector<ProjectOne::R_ID> Robot::positions;
int Robot::ID = -1;

Robot::Robot(double x, double y)
{
    ++ID;
    robot_ID = ID;
    initialX = x;
    initialY = y;
    // Placeholder. Doesn't actually get used properly atm.
    fWidth = 0.35;
    px = x;
    py = y;

    ProjectOne::R_ID msg;   
    msg.R_ID = robot_ID;
    msg.x = x;
    msg.y = y;
    positions.push_back(msg);

    string robotOdom = "robot_" + int2str(robot_ID) + "/odom";
    string robotVel = "robot_" + int2str(robot_ID) + "/cmd_vel";

    RobotOdometry_sub = n.subscribe<nav_msgs::Odometry>(robotOdom,1000,&Robot::ReceiveOdometry,this);
    RobotVelocity_pub = n.advertise<geometry_msgs::Twist>(robotVel,1000);
    ros::spinOnce();
}

void Robot::ReceiveOdometry(nav_msgs::Odometry msg)
{
    //This is the call back function to process odometry messages coming from Stage.    
    px = initialX + msg.pose.pose.position.x;
    py = initialY + msg.pose.pose.position.y;
    ptheta = angles::normalize_angle_positive(asin(msg.pose.pose.orientation.z) * 2);
}

int Robot::selectLeader()
{
    int leader_ID = robot_ID;
    double lowestDistance = 9999999999.9;
    for (unsigned int i=0;i<positions.size();i++)
    {
        double distance = calculateDistance(positions[i].x, positions[i].y, 0.0, 0.0);            
        if (distance < lowestDistance && distance != 0.0)
        {
            leader_ID = positions[i].R_ID;
            lowestDistance = distance;
        }
    }
    ROS_INFO("leader is: %d", leader_ID);
    return leader_ID;
}

double Robot::calculateDistance(double x1, double y1, double x2, double y2)
{
    double deltax = x2 - x1;
    double deltay = y2 - y1;
    double distanceBetween2 = pow(deltax, 2) + pow(deltay, 2);
    double distanceBetween = sqrt(distanceBetween2);
    return distanceBetween;
}

double Robot::calculateHeadingChange(double x, double y)
{
    double deltax = x - px;
    double deltay = y - py;
    double angleBetween = atan2(deltay, deltax);
    double headingChange = angleBetween - ptheta;
    return headingChange;
}

void Robot::align(double x, double y)
{
    ros::Rate loop_rate(10);
    double headingChange = calculateHeadingChange(x, y);
    double angularv = headingChange / 5;
    double heading = ptheta + headingChange;

    while (heading > 2 * M_PI)
    {
        heading -= 2 * M_PI;
    }
    while (heading < 0)
    {
        heading += 2 * M_PI;
    }
    geometry_msgs::Twist msg;
    msg.linear.x = 0;
    msg.angular.z = angularv;
    while (ros::ok())
    {
        RobotVelocity_pub.publish(msg);
    ros::spinOnce();
    ROS_INFO("Heading Change %f pthea is %f %f %f", headingChange, ptheta, px, py);
    loop_rate.sleep();
    }
}

这是调用方法的代码:

int main(int argc, char **argv) {
        ros::init(argc, argv, "robotNode");

    Robot r1(5,10);
    Robot r2(15,20);
    Robot r3(10,30);
    Robot r4(25,16);
    Robot r5(5,28);
    Robot r6(10,10);

    Robot Group[6] = {r1, r2, r3, r4 ,r5, r6};
    std::vector<Robot> Herd;
    int leaderID = r1.selectLeader();

    Robot * leader;

    for (int i=0;i<6;i++) {
        if (Group[i].robot_ID  == leaderID) {
            leader = &Group[i];
        } else {
            Herd.push_back(Group[i]);
        }
    }

    (*leader).align(0.0, 0.0); //Problem area
}

2 个答案:

答案 0 :(得分:7)

问题是您的数组(Group)和向量(Herd)都包含自动对象(r1和朋友)的副本;所以你对那些做的事情都不会影响原件。

您可能希望使用指针代替:

Robot * Group[6] = {&r1, &r2, &r3, &r4, &r5, &r6};
std::vector<Robot*> Herd;

一般情况下,在销毁对象后,需要注意不要取消引用这些指针;在这种情况下你很好,因为数组和向量的生命周期都包含在对象的生命周期内。

使Robot类不可复制可能是有意义的,以防止出现这种错误。 在C ++ 11中,您可以通过删除复制构造函数和复制赋值来完成此操作:

Robot(Robot const &) = delete;
void operator=(Robot const &) = delete;

在较旧的语言版本中,将它们声明为私有,没有实现;或者(更好的是)从一个基类中派生出来。

答案 1 :(得分:3)

这是你的问题:

Robot Group[6] = {r1, r2, r3, r4 ,r5, r6};
int leaderID = r1.selectLeader();

该组包含项目的副本。您没有向我们展示Robot复制构造函数,但我认为它为新构造的Robot分配了唯一的ID。如果是这样,则组中的任何元素都不会具有等于leaderID的ID,因此永远不会设置leader指针。

一种解决方案是使Group数组Robot*指针而不是Robot个数组。您的Herd机器人也会出现类似的问题。