2016-01-04 3 views
1

Интересно, почему простое преобразование из указателя производного класса в указатель базового класса выходит из строя в случае указателя- to-member. Например,Неверное преобразование указателя в члены из «Производные X :: *» в «База X :: *»

struct Base {}; 
    struct Derived: public Base {}; 

    struct X { 
     Derived field; 
    }; 

    int main(int argc, char *argv[]) { 
     Base X::* ptr1 = &X::field; 
     return 0; 
    } 

Выдает ошибку:

$ g++ t.cc 
t.cc: In function ‘int main(int, char**)’: 
t.cc:9:24: error: invalid conversion from ‘Derived X::*’ to ‘Base X::*’ [-fpermissive] 
    Base X::* ptr1 = &X::field; 
         ^

ответ

-1
Base X::* 

означает указатель на элемент X, имеющий тип Base.

Это не то же самое, как

Base* 

Там нет преобразования из

Base* 

к

Base X::* 

и, следовательно, никакого преобразования из

Derived* 

к

Base X::* 

Точно так же нет преобразования между Base X::* и Derived X::*

Пример:

#include <iostream> 
using namespace std; 

class Base 
{ 
}; 

class Derived : public Base 
{ 
}; 

class X { 
public: 
    Derived field1; 
    Base field2; 
}; 


int main() { 
    Base X::* ptr1 = &X::field1;  // Derived X::* to Base X::* OK ? 
    Derived X::* ptr2 = &X::field2; // Base X::* to Derived X::* OK ? 

    return 0; 
} 

Это приведет к

prog.cpp:20:28: error: invalid conversion from 'Derived X::*' to 'Base X::*' [-fpermissive] 
     Base X::* ptr1 = &X::field1; 
          ^
prog.cpp:21:31: error: invalid conversion from 'Base X::*' to 'Derived X::*' [-fpermissive] 
     Derived X::* ptr2 = &X::field2; 

Так что для того, чтобы compil е, он должен быть:

int main() { 
    Derived X::* ptr1 = &X::field1; 
    Base X::* ptr2 = &X::field2; 

    return 0; 
} 

Ниже приведен пример того, как можно использовать указатель на член:

#include <iostream> 
#include <vector> 
using namespace std; 

class Base 
{ 
    public: 
    Base(int g1) : g(g1) {} 
    int g; 
}; 

class Derived : public Base 
{ 
    public: 
    Derived(int d) : Base(d) {} 
}; 

class X { 
public: 
    X(int f1, int f2) : field1(f1), field2(f2) {} 
    Derived field1; 
    Derived field2; 
}; 

void foo(vector<X>& vx, Derived X::*d) 
{ 
    cout << "foo" << endl; 
    for (auto& x : vx) 
    { 
     cout << (x.*d).g << endl; 
    } 
} 

int main() { 
    vector<X> vx {{5, 10}, {50, 100}}; 
    foo(vx, &X::field1); // Print field1.g of all elements in vector vx 
    foo(vx, &X::field2); // Print field2.g of all elements in vector vx 

    return 0; 
} 

Этот выход:

foo 
5 
50 
foo 
10 
100 
3

Потому что нет никакого смысла преобразования между ними.

Вы пытаетесь присвоить «указатель на вещь в классе B» объекту типа «указатель на вещь в классе A».

Взаимосвязь между двумя классами здесь не уместна — Класс А просто не содержит то, что вы хотите указать. Система типов выполняет свою работу.

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

+0

не очень.OP не пытается «назначить« указатель на вещь в классе B »объекту типа« указатель на вещь в классе A. »Оба указателя являются указателями на« вещь в классе X ». Просто разных типов. – SergeyA

+0

Я не уверен, что я понимаю ваш ответ. Я пытаюсь преобразовать 'Derived' в' Base' указатель в классе 'X'. –

+0

@AndreiKouznetsov, см. Мой ответ. Они не конвертируются, поскольку они являются указателями на членов . – SergeyA

1

Это правильно. При использовании указателя на элемент вы не можете использовать указатель на базу для определения производного класса. Указатели на членов не являются указателями! :)

 Смежные вопросы

  • Нет связанных вопросов^_^