Invoke another constructor in the same class

倾然丶 夕夏残阳落幕 提交于 2019-12-24 00:08:57

问题


I have a class with 2 public constructors, that I want to call a private constructor:

class CDeviceTSGetObservationResponse : public CDeviceServerResponse
{
public:
   /**
    * Public constructor. Used to construct a response containing
    * the required information from the TotalStation device.
    *
    * @param horizontalAngle
    *           The horizontal angle.
    * @param verticalAngle
    *           The vertical angle.
    * @param slopeDistance
    *           The slope distance.
    */
   CDeviceTSGetObservationResponse(double horizontalAngle, 
                                   double verticalAngle, 
                                   double slopeDistance)
       : CDeviceTSGetObservationResponse(CDeviceServerResponse::SUCCESS_MESSAGE,
                                         horizontalAngle,
                                         verticalAngle,
                                         slopeDistance) {}

   /**
    * Public constructor. Used to construct a response containing
    * the error message from the TotalStation device.
    *
    * @param errorMsg
    *           The error message for the response.
    */
   CDeviceTSGetObservationResponse(std::string errorMsg)
       : CDeviceTSGetObservationResponse(errorMsg,
                                         0.0,
                                         0.0,
                                         0.0) {}

private:
   /**
    * Private constructor.
    *
    * @param errorMsg
    *           The error message for the response.
    * @param horizontalAngle
    *           The horizontal angle.
    * @param verticalAngle
    *           The vertical angle.
    * @param slopeDistance
    *           The slope distance.
    */
   CDeviceTSGetObservationResponse(std::string errorMsg, 
                                   double      horizontalAngle, 
                                   double      verticalAngle, 
                                   double      slopeDistance) 
       : CDeviceServerResponse(CDeviceServerResponse::TS_GET_OBSERVATION, 
                               errorMsg),
         m_dHorizontalAngle(horizontalAngle), 
         m_dVerticalAngle(verticalAngle), 
         m_dSlopeDistance(slopeDistance){}

   /** The horizontal angle. */
   double m_dHorizontalAngle;

   /** The vertical angle. */
   double m_dVerticalAngle;

   /** The slope distance. */
   double m_dSlopeDistance;
}; // CDeviceTSGetObservationResponse

So the user will either call the constructor passing three booleans if there was no problem, and the error message on the baseclass will default to success.

Or they call the constructor passing in the error message, which will default the values to 0.0.

I thought I could do this with the code above, but I get the following error message:

camd011> make
g++ -c CDeviceTSGetObservationResponse.cpp \
        -I.. -o bin/CDeviceTSGetObservationResponse.o
In file included from CDeviceTSGetObservationResponse.cpp:13:0:
CDeviceTSGetObservationResponse.h: In constructor 'device::response::CDeviceTSGetObservationResponse::CDeviceTSGetObservationResponse(double, double, double)':
CDeviceTSGetObservationResponse.h:44:10: error: type 'device::response::CDeviceTSGetObservationResponse' is not a direct base of 'device::response::CDeviceTSGetObservationResponse'
CDeviceTSGetObservationResponse.h:47:55: error: no matching function for call to 'device::response::CDeviceServerResponse::CDeviceServerResponse()'
CDeviceTSGetObservationResponse.h:47:55: note: candidates are:
CDeviceServerResponse.h:72:4: note: device::response::CDeviceServerResponse::CDeviceServerResponse(device::response::CDeviceServerResponse::EServerMessageIdentifier, std::string)
CDeviceServerResponse.h:72:4: note:   candidate expects 2 arguments, 0 provided
CDeviceServerResponse.h:31:7: note: device::response::CDeviceServerResponse::CDeviceServerResponse(const device::response::CDeviceServerResponse&)
CDeviceServerResponse.h:31:7: note:   candidate expects 1 argument, 0 provided
CDeviceTSGetObservationResponse.h: In constructor 'device::response::CDeviceTSGetObservationResponse::CDeviceTSGetObservationResponse(std::string)':
CDeviceTSGetObservationResponse.h:57:10: error: type 'device::response::CDeviceTSGetObservationResponse' is not a direct base of 'device::response::CDeviceTSGetObservationResponse'
CDeviceTSGetObservationResponse.h:57:42: error: 'errorMeg' was not declared in this scope
CDeviceTSGetObservationResponse.h:60:45: error: no matching function for call to 'device::response::CDeviceServerResponse::CDeviceServerResponse()'
CDeviceTSGetObservationResponse.h:60:45: note: candidates are:
CDeviceServerResponse.h:72:4: note: device::response::CDeviceServerResponse::CDeviceServerResponse(device::response::CDeviceServerResponse::EServerMessageIdentifier, std::string)
CDeviceServerResponse.h:72:4: note:   candidate expects 2 arguments, 0 provided
CDeviceServerResponse.h:31:7: note: device::response::CDeviceServerResponse::CDeviceServerResponse(const device::response::CDeviceServerResponse&)
CDeviceServerResponse.h:31:7: note:   candidate expects 1 argument, 0 provided
CDeviceTSGetObservationResponse.cpp: In member function 'void device::response::CDeviceTSGetObservationResponse::serialize(Archive&, unsigned int)':
CDeviceTSGetObservationResponse.cpp:38:14: error: 'base_object' is not a member of 'boost::serialization'
CDeviceTSGetObservationResponse.cpp:38:69: error: expected primary-expression before '>' token
make: *** [bin/CDeviceTSGetObservationResponse.o] Error 1

回答1:


What you're looking for is delegating constructors and those are only available as of C++11.

For example:

struct A
{
    int x;

    A(): A(10) {}

private:    
    A(int val): x(val) {}
};

int main(int argc, char* argv[])
{
    A a;

    return 0;
}

As you can see here it compiles with C++11, but if you look here the same code does not compile (prior to C++11)




回答2:


It's better to provide a normal private method instead of the private constructor, and call this one in the body of the other constructor definitions.

You can't use member initializer lists for such a private method of course, but initialize all the members as needed in the body of the method will do as well.

UPDATE:
Besides this, your error messages indicate you're using your class in some context that requires a default constructor.




回答3:


OK I removed the private constructor, and re-wrote the two public ones like this:

   /**
    * Public constructor. Used to construct a response containing
    * the required information from the TotalStation device.
    *
    * @param horizontalAngle
    *           The horizontal angle.
    * @param verticalAngle
    *           The vertical angle.
    * @param slopeDistance
    *           The slope distance.
    */
   CDeviceTSGetObservationResponse(double horizontalAngle, 
                                   double verticalAngle, 
                                   double slopeDistance)
       : CDeviceServerResponse(CDeviceServerResponse::TS_GET_OBSERVATION, 
                               CDeviceServerResponse::SUCCESS_MESSAGE),
         m_dHorizontalAngle(horizontalAngle), 
         m_dVerticalAngle(verticalAngle), 
         m_dSlopeDistance(slopeDistance) {}

   /**
    * Public constructor. Used to construct a response containing
    * the error message from the TotalStation device.
    *
    * @param errorMsg
    *           The error message for the response.
    */
   CDeviceTSGetObservationResponse(std::string errorMsg)
       : CDeviceServerResponse(CDeviceServerResponse::TS_GET_OBSERVATION, 
                               errorMsg),
         m_dHorizontalAngle(0.0), 
         m_dVerticalAngle(0.0), 
         m_dSlopeDistance(0.0) {}


来源:https://stackoverflow.com/questions/17454823/invoke-another-constructor-in-the-same-class

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!