1

In my IsSame function I would like to return true if both pointers are pointing to objects of the same type. So only the middle call should return true. D1 and B shouldn't be considered the same.

The below seems to be exactly what I want but is it safe according to the standard?

#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));
}

Output:

0 1 0
4

2 回答 2

6

您正在尝试查看这两个对象是否具有相同的 v-table。C++ 标准没有提到 v-table 指针的存在,更不用说它在对象布局中的位置了。因此,您的解决方案非常不标准,并且您的程序的行为实际上是未定义的。

如果您想查看两个基指针是否具有相同的派生类型但没有 RTTI,您将需要一些机制来让您知道派生类型的 id。这可能意味着一个返回所有派生类型都必须实现的 id 的虚拟方法。

于 2013-04-25T00:41:20.480 回答
4

以下似乎有效:

#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;
}

使用 gcc 4.7.2 编译我得到以下输出:

[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

请注意,如果您决定在没有“运行时类型信息”(RTTI;-fno-rttigcc 中的编译标志)的情况下进行编译,则此代码将无法编译。

于 2013-04-25T00:16:18.327 回答