初始化复杂对象

时间:2016-01-25 13:39:23

标签: c++ c++11 arduino embedded

有哪些选项可用于在全局命名空间中创建具有大量参数的对象?我正在考虑临时对象/变量创建和可读性之间的权衡。

修改

这适用于Arduino上的嵌入式编程。它将是控制一组嵌套对象的可重用库的主要对象。

背景:我有一个测试PCB,可以根据其最终用途进行不同的填充,我需要在一个易于使用的库中涵盖所有这些选项。我试图避免用户在使用对象之前意外遗漏所需的初始化参数。

随意建设性地批评我的代码!

我能想到的两个选项是:

  1. 包含大量参数的构造函数。
  2. 具有单个struct参数的构造函数。
  3. 选项1看起来很乱,很难跟上很多参数 选项2需要一个临时的struct变量来提高可读性。

    下面的示例(通常我将分隔成标题等):

    #include <Arduino.h>
    class NestedClass {
    public:
    
      // Empty constructor for creation of unitialised object. Bad practice?
      NestedClass() {
      }
    
      // Main constructor.
      NestedClass(float voltageReference) :
          voltageReference_(voltageReference) { // Use initialisation list.
      }
    
      float measureVoltage(uint_fast8_t channel) {
        // Convert ADC value to absolute voltage.
        return analogRead(channel) * (voltageReference_ / 1023);
      }
    
    private:
      float voltageReference_;
    };
    
    class ComplexClass {
    public:
    
      enum class Mode
        : uint_fast8_t {
          MODE1,
        MODE2,
        MODE3
      };
    
      struct Parameters {
        uint_fast8_t parameter1;
        uint8_t parameter2;
        float parameter3;
        float parameter4;
        Mode mode;
        float voltageReference;
      };
    
      // Empty constructor for creation of unitialised object. Bad practice?
      ComplexClass(void) {
      }
    
      // Big constructor. Messy when used.
      ComplexClass(uint_fast8_t parameter1, uint8_t parameter2, float parameter3,
          float parameter4, Mode mode, float voltageReference) {
        // Could have used initialisation list instead.
        this->parameter1_ = parameter1;
        this->parameter2_ = parameter2;
        this->parameter3_ = parameter3;
        this->parameter4_ = parameter4;
        this->mode_ = mode;
        this->nestedClass_ = NestedClass(voltageReference); // Wasted temporary object with reassignment?
      }
    
      // Alternative constructor. Looks neater/more legible when used.
      ComplexClass(Parameters parameters) {
        this->parameter1_ = parameters.parameter1;
        this->parameter2_ = parameters.parameter2;
        this->parameter3_ = parameters.parameter3;
        this->parameter4_ = parameters.parameter4;
        this->mode_ = parameters.mode;
        this->nestedClass_ = NestedClass(parameters.voltageReference); // Wasted temporary object with reassignment?
      }
    
      void megaMeasurements() {
        // Do something involving nestedClass.measureVoltage().
      }
    
    private:
      // Maybe put all of these in another struct for neatness?
      uint_fast8_t parameter1_;
      uint8_t parameter2_;
      float parameter3_;
      float parameter4_;
      Mode mode_;
    
      NestedClass nestedClass_;
    };
    
    //####################
    // Start main code.
    //####################
    
    // Option 1:
    // Not immediately obvious which value is for which parameter.
    ComplexClass complexClass(1, 2, 3.30, 2.7, ComplexClass::Mode::MODE2, 5.00);
    
    // Option 2:
    // Unitialised object (sort-of).
    ComplexClass complexClass2;
    
    // Arduino standard function. Called once from main.cpp
    void setup() {
      // Option 2 continued:
      ComplexClass::Parameters parameters;
      parameters.mode = ComplexClass::Mode::MODE2;
      parameters.parameter1 = 1;
      parameters.parameter2 = 2;
      parameters.parameter3 = 3.30;
      parameters.parameter4 = 2.7;
      parameters.voltageReference = 5.00;
      complexClass2 = ComplexClass(parameters); // Reassignment. Wasteful?
    }
    
    // Arduino standard function. Called in a continuous loop after setup().
    void loop() {
      complexClass.megaMeasurements();
      complexClass2.megaMeasurements();
    }
    

1 个答案:

答案 0 :(得分:2)

我的意见(基于我的实践):

  • 具有许多参数的构造函数看起来很混乱,最好避免使用。更多,如果某些参数不好,则无法返回“false”,抱怨的唯一方法是抛出异常。如果你想这样做,最好定义一些带有几个参数的init()函数,如果参数不好,可以选择返回false(或一些错误代码)来抱怨。在这种情况下,最好使用#define或static const声明来避免使用文字数值。

  • 另一种方法是直接(public)或set()方法逐个赋值。在这种情况下,您可以将文字放在代码中。