В моем 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));
}
Выход:
0 1 0
Вы пытаетесь увидеть, имеют ли два объекта одну и ту же v-таблицу. Стандарт C ++ не говорит о наличии указателя v-таблицы, не говоря уже о том, где он будет в макете объекта. Итак, ваше решение тривиально нестандартно, и поведение вашей программы на самом деле не определено.
Если вы хотите увидеть, имеют ли два базовых указателя одинаковый производный тип, но без 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;
}
Компилируя с 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-rtti
флаг компиляции в gcc).