C++ Указатель на Члены
Если у меня есть два класса в одной иерархии с одним и тем же именем и типом, каков "правильный" способ создания указателя на переменную базового класса. Ex.
class A
{
int x;
A():x(1){}
};
class B : public A
{
int x;
B():x(2){}
};
int main(int argc, char *argv[]) {
B classB;
int B::*ptr = &B::x;
int B::*ptr1 = &B::A::x;
int A::*ptr2 = &A::x;
printf("%d,%d,%d\n", classB.*ptr, classB.*ptr1, classB.*ptr2);
return 0;
}
На моем компиляторе (LLVM GCC) будет напечатано 2,1,1, как я и ожидал. Это приводит меня к моим двум вопросам.
Являются ли все три из вышеперечисленных реализаций "безопасными", когда речь идет о стандарте C++?
И если да, то есть ли у каких-либо основных компиляторов несовместимости с любым из них?
1 ответ
Я верю, что все три в безопасности, хотя я не могу цитировать в них главы и стихи из стандарта.:)
Тем не менее, я столкнулся с одной очень конкретной ошибкой в указателях на функции-члены в более старой версии Visual Studio (боюсь, я не помню, какая именно). В частности, у меня была такая структура:
struct optable_entry {
const char *name;
void (*MyClass::run)();
};
const optable_entry operations[] = {
{ "foo", &MyClass::foo },
/* ... */
};
При этом по какой-то причине значения функции-члена не будут правильно инициализированы. В моем случае это был сгенерированный код, так что вместо него было не так уж и сложно заменить его на массивный оператор switch, но это то, что нужно остерегаться - указатели на функции-члены используются достаточно редко, чтобы такие странные угловые случаи, как это, могли быть скрывается в вашем компиляторе.