我在我的代码中使用了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.(这是预期的结果)
基本上我们不想在列表中存储两个相同类型的对象。
答案 0 :(得分:1)
如果你不想要访问者,但是你想要一个快速的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()
问题:前者成为==
,后者成为%
。
答案 1 :(得分:1)
要检查对象是否属于从给定类派生的类,可以使用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();
}
};
此外,此类方法允许您定义是否应将特定后代类视为与其父级不同。