【问题标题】:Pass a class instance to another class by reference通过引用将类实例传递给另一个类
【发布时间】:2015-05-13 11:34:21
【问题描述】:

我正在尝试将我的“状态”类的单个实例传递给我的所有其他类,以便它们都可以设置和获取状态。

我一直在尝试通过将“Status”类通过引用传递到我的“BaseStation”类来做到这一点。代码编译得很好,但是当我从 main 设置状态然后在“BaseStation”中获取状态时它没有改变。

我认为这应该是可能的,所以我一定遗漏了一些东西。

这是我的主要课程

#include "mbed.h"
#include "Global.h"
#include "MODSERIAL.h"
#include "Status.h"
#include "Sensors.h"
#include "BaseStation.h"
#include "Rc.h"
#include "FlightController.h"
#include "NavigationController.h"

MODSERIAL                           _debug(USBTX, USBRX);

//Unused analog pins
DigitalOut                          _spare1(p16);
DigitalOut                          _spare2(p17);
DigitalOut                          _spare3(p18);
DigitalOut                          _spare4(p19);

//Classes
Status                              _status;
Sensors                             _sensors;
BaseStation                         _baseStation;
Rc                                  _rc;
FlightController                    _flightController;
NavigationController                _navigationController;           

int main()
{
    _debug.baud(115200);

    DEBUG("\r\n");  
    DEBUG("********************************************************************************\r\n");
    DEBUG("Starting Setup\r\n");
    DEBUG("********************************************************************************\r\n");

    //Set Status
    _status.initialise();

    //Initialise RC
    //_rc.initialise(_status, p8);

    //Initialise Sensors
    //_sensors.initialise(p13, p14, p28, p27);

    //Initialise Navigation
    //_navigationController.initialise(_status, _sensors, _rc);

    //Initialise Flight Controller
    //_flightController.initialise(_status, _sensors, _navigationController, p21, p22, p23, p24);

    //Initalise Base Station
    _baseStation.initialise(_status, _rc, _sensors, _navigationController, _flightController, p9, p10);

    DEBUG("********************************************************************************\r\n");
    DEBUG("Finished Setup\r\n");
    DEBUG("********************************************************************************\r\n"); 

    _status.setState(Status::STANDBY);
    int state = _status.getState();
    printf("Main State %d\r\n", state);
}

这是我的 Status.cpp

#include "Status.h"

Status::Status(){}

Status::~Status(){}

bool Status::initialise()
{
    setState(PREFLIGHT);
    DEBUG("Status initialised\r\n");
    return true;
}

bool Status::setState(State state)
{
    switch(state)
    {
        case PREFLIGHT:
            setFlightMode(NOT_SET);
            setBaseStationMode(STATUS);
            setBatteryLevel(0);
            setArmed(false);
            setInitialised(false);
            _state = PREFLIGHT;
            DEBUG("State set to PREFLIGHT\r\n");
            return true;

        case STANDBY:

            _state = STANDBY;
            DEBUG("State set to STANDBY\r\n");
            return true;


        case GROUND_READY:

            return true;


        case MANUAL:

            return true;


        case STABILISED:

            return true;


        case AUTO:

            return true;


        case ABORT:

            return true;


        case EMG_LAND:

            return true;


        case EMG_OFF:

            return true;


        case GROUND_ERROR:

            return true;


        default:

            return false;

    }    
}

Status::State Status::getState()
{
    return _state;    
}

bool Status::setFlightMode(FlightMode flightMode)
{
    _flightMode = flightMode;
    return true;
}

Status::FlightMode Status::getFlightMode()
{
    return _flightMode;
}

bool Status::setBaseStationMode(BaseStationMode baseStationMode)
{
    _baseStationMode = baseStationMode;
    DEBUG("Base station mode set\r\n");
    return true;
}

Status::BaseStationMode Status::getBaseStationMode()
{
    return _baseStationMode;
}

bool Status::setBatteryLevel(float batteryLevel)
{
    _batteryLevel = batteryLevel;
    return true;
}

float Status::getBatteryLevel()
{
    return _batteryLevel;
}

bool Status::setArmed(bool armed)
{
    _armed = armed;
    return true;
}

bool Status::getArmed()
{
    return _armed;
}

bool Status::setInitialised(bool initialised)
{
    _initialised = initialised;
    return true;
}

bool Status::getInitialised()
{
    return _initialised;
}

bool Status::setRcConnected(bool rcConnected)
{
    _rcConnected = rcConnected;
    return true;
}

bool Status::getRcConnected()
{
    return _rcConnected;
}

这是我的状态.h

#include "mbed.h"
#include "Global.h"

#ifndef Status_H
#define Status_H

class Status                   // begin declaration of the class
{
  public:                    // begin public section
    Status();     // constructor
    ~Status();                  // destructor

    enum State
    {
        PREFLIGHT,
        STANDBY,
        GROUND_READY,
        MANUAL,
        STABILISED,
        AUTO,
        ABORT,
        EMG_LAND,
        EMG_OFF,
        GROUND_ERROR     
    };

    enum FlightMode
    {
        RATE,
        STAB,
        NOT_SET  
    };

    enum BaseStationMode
    {
        MOTOR_POWER,
        PID_OUTPUTS,
        IMU_OUTPUTS,
        STATUS,
        RC,
        PID_TUNING,
        GPS,
        ZERO,
        RATE_TUNING,
        STAB_TUNING,
        ALTITUDE,
        VELOCITY   
    };

    bool initialise();
    bool setState(State state);
    State getState();
    bool setFlightMode(FlightMode flightMode);
    FlightMode getFlightMode();
    bool setBaseStationMode(BaseStationMode baseStationMode);
    BaseStationMode getBaseStationMode();
    bool setBatteryLevel(float batteryLevel);
    float getBatteryLevel();
    bool setArmed(bool armed);
    bool getArmed();
    bool setInitialised(bool initialised);
    bool getInitialised();
    bool setRcConnected(bool rcConnected);
    bool getRcConnected();

  private:             
    State _state; 
    FlightMode _flightMode;             
    BaseStationMode _baseStationMode;
    float _batteryLevel;
    bool _armed;
    bool _initialised;
    bool _rcConnected;
};

#endif

这是我的 BaseStation.cpp

#include "BaseStation.h"

BaseStation::BaseStation() : _status(status){}

BaseStation::~BaseStation(){}

bool BaseStation::initialise(Status& status, Rc& rc, Sensors& sensors, NavigationController& navigationController, FlightController& flightController, PinName wirelessPinTx, PinName wirelessPinRx)
{   
    _status = status;
    _rc = rc;
    _sensors = sensors;
    _navigationController = navigationController;
    _flightController = flightController;
    _wireless = new MODSERIAL(wirelessPinTx, wirelessPinRx);
    _wireless->baud(57600);
    _wirelessSerialRxPos = 0;

    _thread = new Thread(&BaseStation::threadStarter, this, osPriorityHigh);
    DEBUG("Base Station initialised\r\n");
    return true; 
}

void BaseStation::threadStarter(void const *p)
{
    BaseStation *instance = (BaseStation*)p;
    instance->threadWorker();
}

void BaseStation::threadWorker()
{
    while(_status.getState() == Status::PREFLIGHT)
    {
        int state = _status.getState();
        printf("State %d\r\n", state);
        Thread::wait(100);
    }

    _status.setBaseStationMode(Status::RC);
}

这是我的 BaseStation.h

#include "mbed.h"
#include "Global.h"
#include "rtos.h"
#include "MODSERIAL.h"
#include "Rc.h"
#include "Sensors.h"
#include "Status.h"
#include "NavigationController.h"
#include "FlightController.h"

#ifndef BaseStation_H
#define BaseStation_H

class BaseStation                
{
  public:             
    BaseStation();    
    ~BaseStation();

    struct Velocity
    {
       float accelX;
       float accelY;
       float accelZ;
       float gps;
       float gpsZ;
       float barometerZ;
       float lidarLiteZ;
       float computedX;
       float computedY;
       float computedZ;
    };    

    bool initialise(Status& status, Rc& rc, Sensors& sensors, NavigationController& navigationController, FlightController& flightController, PinName wirelessPinTx, PinName wirelessPinRx);

  private:
    static void threadStarter(void const *p);
    void threadWorker();
    void checkCommand();

    Thread* _thread;
    MODSERIAL* _wireless;
    Status& _status;
    Status status;
    Rc _rc;
    Sensors _sensors;
    NavigationController _navigationController;
    FlightController _flightController;
    char _wirelessSerialBuffer[255];
    int _wirelessSerialRxPos;
};

#endif

我运行时的输出是

********************************************************************************
Starting Setup
********************************************************************************
Base station mode set
State set to PREFLIGHT
Status initialised
Rc initialised
HMC5883L failed id check.IMU initialised
Sensors initialised
State 0
Base Station initialised
********************************************************************************
Finished Setup
********************************************************************************
State set to STANDBY
Main State 1
State 0
State 0

我认为这是因为我实际上并没有传递“状态”的单个实例,而是复制它。

我怎样才能正确地通过引用?

谢谢 乔

【问题讨论】:

  • 看看 www.sscce.org
  • 我投票结束这个问题,因为代码太多。
  • _status = status; 哎呀。
  • 代码太多了。当您注册如何提出问题和提供 MCVE 时,您会被教导。很遗憾您没有费心阅读该材料。

标签: c++ dependency-injection pass-by-reference mbed


【解决方案1】:

您完全误解了 C++ 中引用的工作原理。您只能在构造函数中设置引用,并且只能在成员初始化列表中设置引用,您可以在任何其他位置分配给该引用指向的对象。所以

BaseStation::BaseStation() : _status(status){}

现在你的参考指向会员status

bool BaseStation::initialise(Status& status, Rc& rc, Sensors& sensors, NavigationController& navigationController, FlightController& flightController, PinName wirelessPinTx, PinName wirelessPinRx)
{   
    _status = status;

现在您对 _status 指向的对象进行赋值。所以这段代码其实等价于:

bool BaseStation::initialise(Status& status, Rc& rc, Sensors& sensors, NavigationController& navigationController, FlightController& flightController, PinName wirelessPinTx, PinName wirelessPinRx)
{   
    this->status = status;

一般来说用initialize方法代替constructor不是一个好主意,但万一你有参考,那就更糟了。您需要将其更改为指针,或在构造函数中正确初始化对象。

【讨论】:

    【解决方案2】:
    int  x = 42;
    int  y = 9001;
    
    int& r = x;
    r = y;
    

    现在x9001。您没有更改任何关于 r 的内容。

    同样,在您的代码中,虽然您通过引用接受 Status,但您随后将其值分配给不同的对象。

    您只能初始化引用。在您的情况下,您想将它们链接起来。

    以下是你如何做你想做的事:

    struct Status {};
    struct T
    {
       T(Status& _ref)  // 1. Accept parameter by reference;
          : ref(_ref)   // 2. Initialise member reference;
       {}               // now this->ref is a reference to whatever _ref was a reference to
    
       Status& ref;
    };
    
    int main()
    {
        Status s;
        T obj(s);  // now obj holds a reference to s
    }
    

    【讨论】:

    • 谢谢大家,所以基本上只能在构造函数中通过引用。干杯
    • @JosephBaldwinRoberts:这不是我们真正要说的,不。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-25
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    相关资源
    最近更新 更多