C++ 标准安全类型检查?
在我的C++ 标准安全类型检查?,c++,rtti,C++,Rtti,在我的IsSame函数中,如果两个指针指向相同类型的对象,我想返回true。因此,只有中间调用应该返回trueD1和B不应视为相同 下面的内容似乎正是我想要的,但根据标准,它安全吗 #include <stdio.h> class B { virtual void foo() {} }; class D1 : public B { }; class D2 : public B { }; class D3 : public B { }; bool IsSame(B*a, B*b)
IsSame
函数中,如果两个指针指向相同类型的对象,我想返回true
。因此,只有中间调用应该返回true
D1
和B
不应视为相同
下面的内容似乎正是我想要的,但根据标准,它安全吗
#include <stdio.h>
class B { virtual void foo() {} };
class D1 : public B { };
class D2 : public B { };
class D3 : public B { };
bool IsSame(B*a, B*b) {
if (a == 0 || b == 0)
return false;
return *(intptr_t*)a == *(intptr_t*)b;
}
int main() {
D1 d1;
D2 d2;
D1 d1b;
B b;
printf("%d %d %d\n", IsSame(&d1, &d2), IsSame(&d1, &d1b), IsSame(&d1, &b));
}
以下似乎有效:
#include<typeinfo>
#include<iostream>
class B { virtual void foo() {} };
class D1 : public B { };
class D2 : public B { };
class D3 : public B { };
template<typename T1, typename T2>
bool is_same(const T1& t1, const T2& t2) {
return typeid(t1) == typeid(t2);
}
bool is_same_no_template(const B& b1, const B& b2) {
return typeid(b1) == typeid(b2);
}
int main(){
D1 d1;
D2 d2;
D1 d1b;
B b;
std::cout<<std::boolalpha
<<"d1 == d2 ? "<<is_same(d1, d2)<<std::endl
<<"d1 == d1b ? "<<is_same(d1, d1b)<<std::endl
<<"d1 == b ? "<<is_same(d1, b)<<std::endl;
std::cout<<"No Template"<<std::endl;
std::cout<<std::boolalpha
<<"d1 == d2 ? "<<is_same_no_template(d1, d2)<<std::endl
<<"d1 == d1b ? "<<is_same_no_template(d1, d1b)<<std::endl
<<"d1 == b ? "<<is_same_no_template(d1, b)<<std::endl;
return 0;
}
请注意,如果您决定在没有“运行时类型信息”(RTTI;gcc中的
-fno-RTTI
编译标志)的情况下编译,则不会编译此代码 以下方法似乎有效:
#include<typeinfo>
#include<iostream>
class B { virtual void foo() {} };
class D1 : public B { };
class D2 : public B { };
class D3 : public B { };
template<typename T1, typename T2>
bool is_same(const T1& t1, const T2& t2) {
return typeid(t1) == typeid(t2);
}
bool is_same_no_template(const B& b1, const B& b2) {
return typeid(b1) == typeid(b2);
}
int main(){
D1 d1;
D2 d2;
D1 d1b;
B b;
std::cout<<std::boolalpha
<<"d1 == d2 ? "<<is_same(d1, d2)<<std::endl
<<"d1 == d1b ? "<<is_same(d1, d1b)<<std::endl
<<"d1 == b ? "<<is_same(d1, b)<<std::endl;
std::cout<<"No Template"<<std::endl;
std::cout<<std::boolalpha
<<"d1 == d2 ? "<<is_same_no_template(d1, d2)<<std::endl
<<"d1 == d1b ? "<<is_same_no_template(d1, d1b)<<std::endl
<<"d1 == b ? "<<is_same_no_template(d1, b)<<std::endl;
return 0;
}
请注意,如果您决定在没有“运行时类型信息”(RTTI;gcc中的
-fno-RTTI
编译标志)的情况下编译,则不会编译此代码 您正在尝试查看这两个对象是否具有相同的v形表。C++标准不表示V表指针的存在,更不用说它将在对象的布局中。因此,您的解决方案是非常不标准的,并且您的程序的行为实际上是未定义的
如果要查看两个基指针是否具有相同的派生类型但没有RTTI,则需要某种机制来让您知道派生类型的id。这可能意味着一个虚拟方法返回所有派生类型都必须实现的id。您正在尝试查看这两个对象是否具有相同的v-table。C++标准不表示V表指针的存在,更不用说它将在对象的布局中。因此,您的解决方案是非常不标准的,并且您的程序的行为实际上是未定义的
如果要查看两个基指针是否具有相同的派生类型但没有RTTI,则需要某种机制来让您知道派生类型的id。这可能意味着一个虚拟方法返回一个所有派生类型都必须实现的id。代码甚至没有意义。为什么要进行差异化?转换为
intptr\u t*
有什么意义?我想您是想看看这两个对象是否指向同一个vtable?这绝对不是标准的。你能不能只使用std::is_same::value
(其他的也一样)?@acidzombie24:他们都没有注意到你正在尝试进行动态类型查找。这些解决方案只能在编译时使用静态类型。代码甚至没有意义。为什么要进行差异化?转换为intptr\u t*
有什么意义?我想您是想看看这两个对象是否指向同一个vtable?这绝对不是标准的。你能不能只使用std::is_same::value
(其他的也一样)?@acidzombie24:他们都没有注意到你正在尝试进行动态类型查找。这些解决方案只能在编译时使用静态类型。您正在使用模板,因此T1
和T2
在编译时匹配,因此typeid
的用途在这里真的失去了。(这就是为什么我删除了我的答案。)你应该匹配问题,在比较时只有B*
。@GManNickG,@acidzombie24:恐怕我不明白;((对不起,这里是初学者)。没有模板的版本怎么样?另外,你能详细说明一下为什么typeid
的用途丢失了吗?@acidzombie24:我删除了我的答案,因为它有与这个答案相同的错误信息。这个答案完全没有抓住要点,因为它直接使用了对象,所以它直接在模板参数中包含类型。我修改了回答:使用动态查找完整演示解决方案。@GManNickG:你的回答很好。我禁用运行时信息时,只是想知道typeid是否有效。你为什么要删除你的答案?哦,对了,我以为你使用的是B*而不是模板。-编辑-该死,我没有在中编辑time@Arrieta:您正在使用d1
和d2
d直接来说,因此类型D1
和D2
在编译时就被直接知道了。那么这里就不需要typeid
。问题的关键是我们只有B*
可以使用,并且需要动态地进行类型查找。我犯了同样的错误,别难过。你需要做我的答案所做的事情,然后工作在进行任何进一步的类型检查之前,使用B*
。您没有模板的版本更符合要点,是的。您使用的模板在编译时与T1
和T2
匹配,因此typeid
的目的在这里真的丢失了。(这就是我删除答案的原因。)您应该匹配问题,在比较时只有B*
。@gmannick,@acidzombie24:恐怕我不明白;((对不起,这里是初学者)。没有模板的版本怎么样?另外,你能详细说明一下为什么typeid
的用途丢失了吗?@acidzombie24:我删除了我的答案,因为它有与这个答案相同的错误信息。这个答案完全没有抓住要点,因为它直接使用了对象,所以它直接在模板参数中包含类型。我修改了回答:使用动态查找完整演示解决方案。@GManNickG:你的回答很好。我禁用运行时信息时,只是想知道typeid是否有效。你为什么要删除你的答案?哦,对了,我以为你使用的是B*而不是模板。-编辑-该死,我没有在中编辑time@Arrieta:您正在使用d1
和d2
d直接来说,因此类型D1
和D2
在编译时就被直接知道了。那么这里就不需要typeid
。问题的关键是我们只有B*
可以使用,并且需要动态地进行类型查找。我犯了同样的错误,别难过。你需要做我的答案所做的事情,然后工作在您进行任何进一步的类型检查之前,请使用B*
。您没有模板的版本更符合这一点,是的。遗憾的是,标准没有指定获取vtable ptr的方法。@acidzombie24,正如用户315052所指出的,重点是标准没有
[Prompt] g++ example.cpp -std=c++11
[Prompt] ./a.out
d1 == d2 ? false
d1 == d1b ? true
d1 == b ? false
No Template
d1 == d2 ? false
d1 == d1b ? true
d1 == b ? false