【问题标题】:Reducing the number of overloaded functions and constructors减少重载函数和构造函数的数量
【发布时间】:2019-02-18 02:21:56
【问题描述】:

考虑以下类定义:

class Car : public Vehicle {
    private:
        TouchScreen a;
        RadioAntenna b;
        Blah c;
    public:
        Car(TouchScreen &a1) {
            a = a1; //copy ctor
        }
        Car(RadioAntenna &b1) {
            b = b1;
        }
        Car(Blah &c1) {
            c = c1;
        }
        void update(Touchscreen &a1) {
            a.update(a1);
        }
        void update(RadioAntenna &b1) {
            b.update(b1);
        }
        void update(Blah &c1) {
            c.update(c1);
        }
}

class Fleet {
    private:
        std::map<int, Car> _fleet; //vehicle number, Car
    public:
        template <typename T>
        void update(int vehicle_num, T &t) {
            auto it = _fleet.find(vehicle_num);
            if (it == _fleet.end()) {
                _fleet[vehicle_num] = Car(t);
            }
            else {
                it->second.update(t);
            }
        }
}

Fleet 包含汽车的集合。如果要更新特定汽车的成员变量,

Fleet f;
f.update<TouchScreen>(4, a1);
f.update<Blah>(10, c1); 

未来,可以在 Car 内部定义更多的类实例。有没有办法减少重载的 Constructor 和 update() 函数的数量?也许使用模板?我觉得它看起来丑陋,设计明智,使用了这么多重载函数。

【问题讨论】:

    标签: c++ templates polymorphism overloading


    【解决方案1】:

    我的想法是使用 std::any 来做这件事。假设 Car 类中的每种类型只有一个实例。

    这是我的解决方案:

    class Car : public Vehicle {
    private:
        std::unordered_map<std::string, std::any> components;
    public:
        Car(std::any &obj) {
            std::string typeName(obj.type().name());
            components.insert(make_pair(typeName, obj));
        }
    
        template<typename T> 
        void update(T& found, T &a1)
        {
            (std::any_cast<T>(found)).update(std::any_cast<T>(a1));
        }
    
        void update(std::any  &a1) {
            std::string typeName(a1.type().name());
            std::any found  =  components.find(typeName);
            if (found != components.end())
            {
                if (typeName ==  std::string(typeid(TouchScreen).name())
                {
                    update<TouchScreen>(found.second, a1);
                }
                else if (typeName ==  std::string(typeid(RadioAntenna ).name())
                {
                    update<RadioAntenna>(found.second, a1);
                }
                else if (typeName ==  std::string(typeid(Blah  ).name())
                {
                    update<Blah>(found.second, a1);
                }
    
            }
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      替代代码可以是:

      void Car::update(Touchscreen* a1=nullptr, RadioAntenna* b1=nullptr, Blah* c1=nullptr ) {
              if(a1) a.update(*a1);
              if(b1) b.update(*b1);
              if(c1) c.update(*c1);                        
      }
      

      【讨论】:

      • 这些 if 语句中的条件应该颠倒过来。
      • 不,我的意思是您正在检查指针是否为空,然后取消引用它们。您应该检查它们是否为 not 空值。所以if (a1) a.update(*a1)等等。
      猜你喜欢
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多