Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.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++ 如何通过更好的抽象避免typeid?_C++ - Fatal编程技术网

C++ 如何通过更好的抽象避免typeid?

C++ 如何通过更好的抽象避免typeid?,c++,C++,我在代码中使用了typeid,但在我看来,如果我避免使用typeid,代码可能会更干净 如果我们想存储类的类型,为什么首先要选择面向对象的语言 但我一次又一次地看到这种模式,我不知道如何避免它 所以我在想,这段代码是否可以写得更干净,有更好的抽象 代码如下: class A { public: string type; }; template <typename T> class B : public A { public: B() { type =

我在代码中使用了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;
}
A类{
公众:
字符串类型;
};
模板
B类:公共A{
公众:
B(){
type=typeid(T).name();
}
};
类注册表{
私人:
std::向量表;
公众:
无效附加(A*A){
int=0;
对于(A*el:列表){
如果(a->type==el->type){
发现=1;
打破
}
}
如果(!找到)
列表。推回(a);
}
int size(){
返回list.size();
}
};
int main(int argc,字符**argv){
注册处注册;
A*b_int1=新的b();
A*b_int2=新的b();
A*b_float=新的b();
注册附加(b_int1);
注册附加(b_int2);
注册附加(b_浮动);

cout如果您不想要访客,但您想要快速的RTTI,我建议您查看以下文件:

这个想法是:

  • 每个类都为自己的类型分配了一个不同的素数(例如,
    a::my_type=2
    B::my_type=3
  • 然后为每个类另外分配其类型与基类值(如果有)的乘积(例如,
    A::can\u cast=A::my\u type
    B::can\u cast=B::my\u type*A::can\u cast;

这解决了
是相同的\u动态的(
是基本的\u动态的()
问题优雅:前者变成
==
,后者变成
%
要检查对象是否属于从给定类派生的类,可以使用
动态\u cast
并将结果与
null ptr
进行比较。不幸的是,鉴于我们需要检查未知类型的这一事实,我们需要必须对类
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();
  }
};
#定义类型#比较\
虚拟布尔比较(A*rhs)\
{ \
返回动态_cast(rhs)!=nullptr\
}
甲级{
公众:
类型比较
};
模板
B类:公共A{
公众:
类型比较
};
类注册表{
私人:
std::向量表;
公众:
无效附加(A*A){
int=0;
对于(A*el:列表){
如果(a->比较(el)&&el->比较(a)){
发现=1;
打破
}
}
如果(!找到)
列表。推回(a);
}
int size(){
返回list.size();
}
};

此外,这种方法允许您定义是否应将特定的子类视为与其父类不同。

typeid(T).name()
这不能保证是有意义的…所以最好只存储返回的
类型信息。@loro,更像是不稳定类层次结构的反模式。除非实现a循环访问者模式,但这只是回到使用RTTI。为什么a不是多态的?@arash Compare
typeid(*a)
typeid(*el)
append
中。基类中至少需要一个虚拟函数。析构函数是一个流行的选择。@arash:“基本上,我们不想在一个列表中存储两个相同类型的对象。”…为什么?在需要(多态)列表的地方,您在做什么值,但每个值都必须是不同的类型?在我看来,如果你需要“一次又一次地”这样做,那么你在类型上似乎做错了什么。