当前位置:C++技术网 > 资讯 > C++代码编写技巧——分析老外的库

C++代码编写技巧——分析老外的库

更新时间:2016-06-10 14:41:06浏览次数:1+次

废话不多说,先来一段代码:


class Urg_driver : public Lidar
    {
    public:
        enum {
            Default_baudrate = 115200,
            Default_port = 10940,
            Infinity_times = -1,
        };

        Urg_driver(void);
        virtual ~Urg_driver(void);

        static std::vector<std::string> find_ports(void);
        static std::vector<std::string> find_ports(std::vector<int>&
                                                   is_urg_ports);
        const char* what(void) const;

        bool open(const char* device_name, long baudrate = Default_baudrate,
                  connection_type_t type = Serial);
        void close(void);
        bool is_open(void) const;

        void set_timeout_msec(int msec);

        bool laser_on(void);
        bool laser_off(void);

        void reboot(void);

        void sleep(void);
        void wakeup(void);
        bool is_stable(void);

        //!  Starts data measurement process
        bool start_measurement(measurement_type_t type = Distance,
                               int scan_times = Infinity_times,
                               int skip_scan = 0);

        //!  Receives measurement data
        bool get_distance(std::vector<long>& data, long *time_stamp = NULL);
        bool get_distance_intensity(std::vector<long>& data,
                                    std::vector<unsigned short>& intensity,
                                    long *time_stamp = NULL);

        bool get_multiecho(std::vector<long>& data_multi,
                           long* time_stamp = NULL);

        bool get_multiecho_intensity(std::vector<long>& data_multiecho,
                                     std::vector<unsigned short>&
                                     intensity_multiecho,
                                     long* time_stamp = NULL);

        bool set_scanning_parameter(int first_step, int last_step,
                                    int skip_step = 1);

        //!  Stops data measurement process
        void stop_measurement(void);

        //!  Synchronization of timestamps
        bool set_sensor_time_stamp(long time_stamp);
        long get_sensor_time_stamp(void);

        //!  Angle conversion functions
        double index2rad(int index) const;
        double index2deg(int index) const;
        int rad2index(double radian) const;
        int deg2index(double degree) const;
        int rad2step(double radian) const;
        int deg2step(double degree) const;
        double step2rad(int step) const;
        double step2deg(int step) const;
        int step2index(int step) const;

        int min_step(void) const;
        int max_step(void) const;
        long min_distance(void) const;
        long max_distance(void) const;
        long scan_usec(void) const;
        int max_data_size(void) const;
        int max_echo_size(void) const;

        const char* product_type(void) const;
        const char* firmware_version(void) const;
        const char* serial_id(void) const;
        const char* status(void) const;
        const char* state(void) const;

        int raw_write(const char* data, size_t data_size);
        int raw_read(char* data, size_t max_data_size, int timeout);
        int raw_readline(char* data, size_t max_data_size, int timeout);
        void* raw_urg(void);
        void set_measurement_type(measurement_type_t type);

    private:
        Urg_driver(const Urg_driver& rhs);
        Urg_driver& operator = (const Urg_driver& rhs);

        struct pImpl;/////!!!!!!就是它,技巧就这里
        std::auto_ptr<pImpl> pimpl;
    };
}
然后接着看:
void Urg_driver::stop_measurement(void)
{
    urg_stop_measurement(&pimpl->urg_);
}

long Urg_driver::get_sensor_time_stamp(void)
{
    return urg_time_stamp(&pimpl->urg_);
}

double Urg_driver::index2rad(int index) const
{
    return urg_index2rad(&pimpl->urg_, index);
}


double Urg_driver::index2deg(int index) const
{
    return urg_index2deg(&pimpl->urg_, index);
}


int Urg_driver::rad2index(double radian) const
{
    return urg_rad2index(&pimpl->urg_, radian);
}


int Urg_driver::deg2index(double degree) const
{
    return urg_deg2index(&pimpl->urg_, degree);
}


int Urg_driver::rad2step(double radian) const
{
    return urg_rad2step(&pimpl->urg_, radian);
}


int Urg_driver::deg2step(double degree) const
{
    return urg_deg2step(&pimpl->urg_, degree);
}


double Urg_driver::step2rad(int step) const
{
    return urg_step2rad(&pimpl->urg_, step);
}


double Urg_driver::step2deg(int step) const
{
    return urg_step2deg(&pimpl->urg_, step);
}


int Urg_driver::step2index(int step) const
{
    return urg_step2index(&pimpl->urg_, step);
}


int Urg_driver::min_step(void) const
{
    int min_step;
    int max_step;

    urg_step_min_max(&pimpl->urg_, &min_step, &max_step);

    return min_step;
}


大家注意到函数的实现没有?每个参数都有一个神奇的:


&pimpl->urg_
这个东西是什么呢?为什么会出现?然后我们仔细看代码实现,找到了它:



struct Urg_driver::pImpl
{
    urg_t urg_;
    bool is_opened_;
    measurement_type_t last_measure_type_;
    long time_stamp_offset_;

    string product_type_;
    string firmware_version_;
    string serial_id_;
    string status_;
    string state_;


    pImpl(void)
        : is_opened_(false), last_measure_type_(Distance), time_stamp_offset_(0)
    {
    }


    void adjust_time_stamp(long *time_stamp)
    {
        if (time_stamp) {
            *time_stamp += time_stamp_offset_;
        }
    }
};
这是一个结构体,本文章的意义就在于说明作者为什么要这么用:


分析这个结构体的特点:

1.它包含了所有的基础的操作变量。

2.里面包含了基础的私有变量操作。

3.减少了头文件的代码行数!!!。

4.当进行逐层封装的时候,让封装的可读性变好。一层覆盖一层