c++

I wonder why a simple conversion from a derived class pointer to the base class pointer fails in the case of the pointer-to-member conversion. For example,

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

    struct X {
      Derived field;
    };

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

Gives the error:

$ 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;
                        ^

Base X::*

means a pointer to a member of X having type Base.

It is not the same as

Base*

There are no conversion from

Base*

to

Base X::*  

and consequently no conversion from

Derived*

to

Base X::*  

Likewise there are no conversion between Base X::* and Derived X::*

Example:

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

This will result in

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;  

So in order to compile, it needs to be:

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

  return 0;
}

Below is an example of how pointer-to-member can be used:

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

This will output:

foo
5
50
foo
10
100

Because there is no meaningful conversion between the two.

You're trying to assign a "pointer to a thing in Class B" to an object of type "pointer to a thing in Class A".

The inheritance relationship between the two classes isn't relevant here — Class A simply does not contain the thing you want to point to. The type system is doing its job.

You'll have to find some other way of doing whatever it is that you're trying to do. Unfortunately you didn't say what that is, so I can't help further!


This is correct. When using pointer-to-member, you can not use a pointer to base to identify a derived class. Pointers-to-members are not pointers! :)

链接地址: http://www.djcxy.com/p/23332.html

上一篇: 作为模板参数降级指向成员的指针

下一篇: C ++