如何用更好的抽象来避免类型化

How to avoid typeid with better abstraction?

本文关键字:类型化 抽象 何用 更好      更新时间:2023-10-16

我在代码中使用typeid,但在我看来,如果我避免typeid,代码可以更干净。

如果我们想存储类的类型,为什么首先要选择面向对象的语言呢?

但是我一次又一次地看到这种模式,我不知道如何避免它。

所以我在想,如果这段代码可以写得更干净,更好的抽象?

代码如下:

class A {
public:
    string type;
};
template <typename T>
class B : public A {
public:
    B() {
        type = typeid(T).name();
    }
};
class Registry {
private:
    std::vector<A *> list;
public:
    void append(A * a) {
        int found = 0;
        for (A * el : list) {
            if (a->type == el->type) {
            found = 1;
            break;
        }
    }
    if (!found)
        list.push_back(a);
    }
    int size() {
        return list.size();
    }
};
int main(int argc, char **argv) {
    Registry reg;
    A * b_int1 = new B<int>();
    A * b_int2 = new B<int>();
    A * b_float = new B<float>();
    reg.append(b_int1);
    reg.append(b_int2);
    reg.append(b_float);
    cout << reg.size() << endl;
    return 0;
}

输出为2。(这是预期的结果)

基本上我们不希望在一个列表中存储两个相同类型的对象

如果你不想要访客,但你想要一个快速的RTTI,我建议你看看这篇文章:http://www.stroustrup.com/fast_dynamic_casting.pdf

思路是:

  • 每个类被分配一个不同的素数为它自己的类型(例如,A::my_type = 2;B::my_type = 3)
  • 然后每个类被额外分配其类型和基类值的乘积,如果有的话(例如,A::can_cast = A::my_type;B::can_cast = B::my_type * A::can_cast;)

这优雅地解决了is_same_dynamic()is_base_dynamic()的问题:前者变成了==,后者变成了%

要检查对象是否属于从给定类派生的类,可以使用dynamic_cast<T*>并将结果与nullptr进行比较。不幸的是,考虑到我们需要对未知类型检查这一事实,我们被迫为A类的每个后代实现一次这样的比较方法,但这可以使用#define来简化。

总结起来,我可能会这样写:

#define TYPE_COMPARISON 
virtual bool compare(A* rhs) 
{ 
  return dynamic_cast<decltype(this)>(rhs) != nullptr; 
}
class A {
public:
  TYPE_COMPARISON
};
template <typename T>
class B : public A {
public:
  TYPE_COMPARISON
};
class Registry {
private:
  std::vector<A *> list;
public:
  void append(A * a) {
    int found = 0;
    for (A * el : list) {
      if (a->compare(el) && el->compare(a)) {
        found = 1;
        break;
      }
    }
    if (!found)
      list.push_back(a);
  }
  int size() {
    return list.size();
  }
};

而且,这样的方法允许您定义一个特定的后代类是否应该被视为与其父类不同。