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, как я и ожидал. Это приводит меня к моим двум вопросам.

  1. Являются ли все три из вышеперечисленных реализаций "безопасными", когда речь идет о стандарте C++?

  2. И если да, то есть ли у каких-либо основных компиляторов несовместимости с любым из них?

1 ответ

Решение

Я верю, что все три в безопасности, хотя я не могу цитировать в них главы и стихи из стандарта.:)

Тем не менее, я столкнулся с одной очень конкретной ошибкой в ​​указателях на функции-члены в более старой версии Visual Studio (боюсь, я не помню, какая именно). В частности, у меня была такая структура:

struct optable_entry {
    const char *name;
    void (*MyClass::run)();
};

const optable_entry operations[] = {
    { "foo", &MyClass::foo },
    /* ... */
};

При этом по какой-то причине значения функции-члена не будут правильно инициализированы. В моем случае это был сгенерированный код, так что вместо него было не так уж и сложно заменить его на массивный оператор switch, но это то, что нужно остерегаться - указатели на функции-члены используются достаточно редко, чтобы такие странные угловые случаи, как это, могли быть скрывается в вашем компиляторе.

Другие вопросы по тегам