Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使我的类更加独立于平台?_C++_Oop_Design Patterns - Fatal编程技术网

C++ 如何使我的类更加独立于平台?

C++ 如何使我的类更加独立于平台?,c++,oop,design-patterns,C++,Oop,Design Patterns,我有个问题。我已经编写了一个GPS模块,可以在飞行中检测消息的类型,并在需要时进行配置。我已经写了好几节课了。为了使代码更独立于平台(stm32),我创建了一个具有baic I/o操作的IStreamDevice接口。它起作用了。一切看起来都很好,但这两个班显然是结合在一起的。这就是我有几个问题的原因: 如何避免将IStreamDevice传递给所有设备 如何使整个设计更加独立于平台(和操作系统)?我们计划在最近的将来迁移到另一个操作系统。它符合POSIX标准。我想我将能够在那里实现我的IStr

我有个问题。我已经编写了一个GPS模块,可以在飞行中检测消息的类型,并在需要时进行配置。我已经写了好几节课了。为了使代码更独立于平台(stm32),我创建了一个具有baic I/o操作的
IStreamDevice
接口。它起作用了。一切看起来都很好,但这两个班显然是结合在一起的。这就是我有几个问题的原因:

  • 如何避免将IStreamDevice传递给所有设备
  • 如何使整个设计更加独立于平台(和操作系统)?我们计划在最近的将来迁移到另一个操作系统。它符合POSIX标准。我想我将能够在那里实现我的
    IStreamDevice
    接口(我可以使用的总线是UART和SPI。在我当前的版本中,我只使用UART)。我错了吗

     class IStreamDevice
        {
                public:
                virtual ~IStreamDevice() {}
                virtual uint32_t read(uint8_t* data, uint32_t size) = 0;
                virtual uint32_t write(const uint8_t* data, uint32_t size) = 0;    
                virtual uint32_t bytesToRead() const = 0;
                virtual uint32_t bytesToWrite() const = 0;  
        };
    
        class GPSModule {
        public:
    
            GPSModule(periph::IStreamDevice *source);
            ~GPSModule();
    
            void turnDevice1Messages();
            void turnDevice2Messages();
            void configureDevice1(...);
            void configureDevice2(...);
            void Scan();
    
        private:
            Device1Configurator *_device1_configurator;
            Device2Configurator *_device2_configurator;
            StreamDeviceScanner*_scanner;
            periph::IStreamDevice *_source;
        };
    
        GPSModule::GPSModule(periph::IStreamDevice *source): _source(source)
        {
            _scanner= new StreamDeviceScanner(_source);
            _device1_configurator = new Device1Configurator(_source);
            _device2_configurator = new Device2Configurator(_source);
        }
    
        GPSModule::~GPSModule()
        {
            delete _scanner;
        }
    
        void GPSModule::Scan()
        {
            _scanner->Scan();
        }
    
        void GPSModule::turnDevice1Messages()   {
            _device1_configurator->turnMessages();
        }
    
        class StreamDeviceScanner{
        public:
            StreamDeviceScanner(periph::IStreamDevice *source);
            ~StreamDeviceScanner();
            void Scan();
    
        private:
            typedef enum
            {
                WAITING_SYNC,
                WAITING_DEVICE1_MSG,
                WAITING_DEVICE2_MSG
            } states_t;
    
            periph::IStreamDevice *_source;
            ProtocolScanner *_protocol_scanner;
            states_t _state;
        private:
    
            states_t _catchSync();
            uint32_t _read(uint8_t* data, uint32_t length) { return _source->read(data,length); }
            uint32_t _bytesToRead() const { return _source->bytesToRead(); }
        };
    
        StreamDeviceScanner::StreamDeviceScanner(periph::IStreamDevice *source):
        _source(source),
        _state(WAITING_SYNC)
        {
            _protocol_scanner = new ProtocolScanner(source);
        }
    
    
        StreamDeviceScanner::~StreamDeviceScanner()
        {
            delete _protocol_scanner;
        }
    
    
        void StreamDeviceScanner::Scan()
        {
            while  (_source->bytesToRead()) {
    
                    switch (_state)
                    {
                        case WAITING_SYNC:
                            _state = _catchSync();
    
                        break;
    
                        case WAITING_DEVICE1_MSG:
                            _protocol_scanner->Device1Scan()
        _state = WAITING_SYNC;
    
                        break;
    
                        case WAITING_DEVICE2_MSG:
                            _protocol_scanner->Device2Scan() 
        _state = WAITING_SYNC;
                        break;
                    }
    
            }
        }
    
        class ProtocolScanner {
        private:
            Device1Scanner *_Device1Scanner;
            Device2Scanner *_Device2Scanner;
        public:
            ProtocolScanner(periph::IStreamDevice *source)
            {
                _Device1Scanner = new Device1Scanner(source);
                _Device2Scanner = new Device2Scanner(source);
            }
    
            ~ProtocolScanner()
            {
                delete _Device1Scanner;
                delete _Device1Scanner;
            }
    
            bool Device1Scan() const { return _Device1Scanner->Scan(); }
            bool Device2Scan() const { return _Device2Scanner->Scan(); }
        };
    
        class Device1Scanner {
        public:
            Device1Scanner(periph::IStreamDevice *source);
            ~Device1Scanner();
            bool Scan();
    
        private:
            enum { BUFFER_LENGTH = 8192 };
    
            typedef enum {
                Waiting_Header,
                Waiting_Payload,
                Waiting_Checksum
            } state_t;
    
    
            uint8_t _buffer[BUFFER_LENGTH];
    
            periph::IStreamDevice *_source;
    
            state_t _state;
    
            Device1Parser *_destination;
            Device1Scanner::NovatelMessage _message;
    
        private:
            uint32_t _read(uint8_t* data, uint32_t size) { return _source->read(data,size); }
            const uint32_t _bytesToRead() const { return _source->bytesToRead(); }
    
            bool _receiveHeader();
            bool _receivePayload();
            bool _receiveChecksum();
            bool _validChecksum() const;
    
        };
    
    Device2Scanner
    看起来完全一样。我想听听任何人对设计的意见


  • 我看你的设计没有任何固有的问题。您的
    IStreamWriter
    接口似乎是底层总线的适当抽象,而不依赖于特定的总线细节。这符合依赖倒置原则和契约式设计方法。我也没有看到你们班上的紧密耦合。根据接口规范,您通过其处理程序访问总线,而不依赖于实际总线处理类的实现


    所示代码中没有任何平台依赖性。如果每个平台的总线处理不同,那么除了根据平台为
    IStreamWriter
    提供不同的实现之外,您没有什么可以做的

    编辑完这个问题后,请给我发送一封邮件。所以没有什么好办法可以避免将IStreamWriter传递给所有的班级成员?当我看代码时,我非常怀疑它是否能做得更好。我想得太多了吗?正如我在上面所写的,将IStreamDevice传递给所有成员让我头疼。@enter\u\u机器人好吧,你必须以某种方式链接不同的对象,对吗?这里没有太多的选择。
    StreamWriter
    可以从您身边经过;它可以是全球性的(通常,这是一个坏主意,但这取决于环境和上下文)。您还可以使用外部存储对象来存储您的
    StreamWriter
    ,并从需要的任何位置在内部查询存储-但它不会为您节省任何东西,而且这是一个严重的过度工程,您只需要将用户连接到此存储,而不是连接到实际的
    StreamWriter
    再多说一句——通常您对软件提出的要求越多,您的开销就越大(可能是性能、复杂性或任何其他类型的影响)。这里需要将您的实体显式连接到
    StreamWriter
    ,并且需要编写接口(这是最重要的部分,您可以接受)-IMHO,这是为您获得的模块化和平台独立性付出的一个小代价。