473,796 Members | 2,558 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Pointers to Members question

Hi,

Is this code okay and compliant with the standard. As far as I
understand it is correct but I just want to make sure.

Thank you,
Ben.

----

#include <iostream>
using namespace std;

class Base {
public:
typedef void (Base::*PMethod )(void);
void Invoke (PMethod p) {(this->*p)();}
};

class Derived : public Base {
public:
void Method (void) {cout << "Hello World" << endl;}
};

int main (void) {
Derived x;
// *** Is the static_cast correct here ? Or could this leads
// to undefined behavior on some platform / compiler ?
x.Invoke(static _cast<Base::PMe thod>(&Derived: :Method));
return 0;
}
Sep 21 '07 #1
6 1221
Ben Thomas wrote:
Hi,

Is this code okay and compliant with the standard. As far as I
understand it is correct but I just want to make sure.

Thank you,
Ben.

----

#include <iostream>
using namespace std;

class Base {
public:
typedef void (Base::*PMethod )(void);
void Invoke (PMethod p) {(this->*p)();}
};

class Derived : public Base {
public:
void Method (void) {cout << "Hello World" << endl;}
};

int main (void) {
Derived x;
// *** Is the static_cast correct here ? Or could this leads
// to undefined behavior on some platform / compiler ?
x.Invoke(static _cast<Base::PMe thod>(&Derived: :Method));
return 0;
}
Generally speaking, a member of derived is NOT a member of base,
and that's why the conversion does not exist, and you have to resort
to some tricks (like casts) to silence the compiler that complains
otherwise. The static cast (as I understand it) would be called for
if you have a pointer to member of 'Base' ('Base::*ptr'), somehow
it was converted to a pointer to a member of 'Derived' ('Derived::*')
and then your base wants to call it. Then, since _originally_ the
pointer *was* to a member of 'Base', you're ok to use 'static_cast'.
If the pointer *never was* to a member of 'Base', casting is *not*
the right thing to do. You're correct suspecting that the behaviour
is undefined.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 21 '07 #2
On 2007-09-21 16:36:43 -0400, "Victor Bazarov" <v.********@com Acast.netsaid:
>
The static cast (as I understand it) would be called for
if you have a pointer to member of 'Base' ('Base::*ptr'), somehow
it was converted to a pointer to a member of 'Derived' ('Derived::*')
and then your base wants to call it. Then, since _originally_ the
pointer *was* to a member of 'Base', you're ok to use 'static_cast'.
If the pointer *never was* to a member of 'Base', casting is *not*
the right thing to do. You're correct suspecting that the behaviour
is undefined.
More generally, once you cast it, you have to cast it back to its
original type to get well-defined behavior.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Sep 21 '07 #3
On Sep 21, 10:36 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
Ben Thomas wrote:
Is this code okay and compliant with the standard. As far as I
understand it is correct but I just want to make sure.
#include <iostream>
using namespace std;
class Base {
public:
typedef void (Base::*PMethod )(void);
void Invoke (PMethod p) {(this->*p)();}
};
class Derived : public Base {
public:
void Method (void) {cout << "Hello World" << endl;}
};
int main (void) {
Derived x;
// *** Is the static_cast correct here ? Or could this leads
// to undefined behavior on some platform / compiler ?
x.Invoke(static _cast<Base::PMe thod>(&Derived: :Method));
return 0;
}
Generally speaking, a member of derived is NOT a member of base,
and that's why the conversion does not exist, and you have to resort
to some tricks (like casts) to silence the compiler that complains
otherwise. The static cast (as I understand it) would be called for
if you have a pointer to member of 'Base' ('Base::*ptr'), somehow
it was converted to a pointer to a member of 'Derived' ('Derived::*')
and then your base wants to call it. Then, since _originally_ the
pointer *was* to a member of 'Base', you're ok to use 'static_cast'.
If the pointer *never was* to a member of 'Base', casting is *not*
the right thing to do. You're correct suspecting that the behaviour
is undefined.
I think you've got it backwards. Pointer to member casts work
the opposite of normal pointer casts. There is an implicit D::*
to B::* conversion (no cast needed). A static_cast is needed
for D::* to B::*, however, and the using it is only legal if the
B it is used with is actually a D. Which is the case above. So
while the above may be as ugly as sin, it is perfectly legal
(and was used for callbacks in one GUI library---XViews, I
think---that was widely used in the past).

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Sep 23 '07 #4
James Kanze wrote:
On Sep 21, 10:36 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
>Ben Thomas wrote:
>>Is this code okay and compliant with the standard. As far as I
understand it is correct but I just want to make sure.
>>#include <iostream>
using namespace std;
>>class Base {
public:
typedef void (Base::*PMethod )(void);
void Invoke (PMethod p) {(this->*p)();}
};
>>class Derived : public Base {
public:
void Method (void) {cout << "Hello World" << endl;}
};
>>int main (void) {
Derived x;
// *** Is the static_cast correct here ? Or could this leads
// to undefined behavior on some platform / compiler ?
x.Invoke(static _cast<Base::PMe thod>(&Derived: :Method));
return 0;
}
>Generally speaking, a member of derived is NOT a member of base,
and that's why the conversion does not exist, and you have to resort
to some tricks (like casts) to silence the compiler that complains
otherwise. The static cast (as I understand it) would be called for
if you have a pointer to member of 'Base' ('Base::*ptr'), somehow
it was converted to a pointer to a member of 'Derived' ('Derived::*')
and then your base wants to call it. Then, since _originally_ the
pointer *was* to a member of 'Base', you're ok to use 'static_cast'.
If the pointer *never was* to a member of 'Base', casting is *not*
the right thing to do. You're correct suspecting that the behaviour
is undefined.

I think you've got it backwards. Pointer to member casts work
the opposite of normal pointer casts. There is an implicit D::*
to B::* conversion (no cast needed).
Nope. *You* got it backwards. Every member of 'B' is a member of
'D' as well (by inheritance), so 'B::*' =='D::*' requires no special
syntax, its implicit (modulo all the "available" and "unambiguou s"
cruft). [conv.mem]/2.

For the pointers to *objects*, however, it's reverse: Every 'D' is
a 'B' (modulo "available" and "unambiguou s"), so conversion from 'D*'
to 'B*' is implicit.
A static_cast is needed
for D::* to B::*, however, and the using it is only legal if the
B it is used with is actually a D. Which is the case above. So
while the above may be as ugly as sin, it is perfectly legal
(and was used for callbacks in one GUI library---XViews, I
think---that was widely used in the past).
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 24 '07 #5
On Sep 24, 3:59 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
James Kanze wrote:
On Sep 21, 10:36 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
[...]
Generally speaking, a member of derived is NOT a member of base,
and that's why the conversion does not exist, and you have to resort
to some tricks (like casts) to silence the compiler that complains
otherwise. The static cast (as I understand it) would be called for
if you have a pointer to member of 'Base' ('Base::*ptr'), somehow
it was converted to a pointer to a member of 'Derived' ('Derived::*')
and then your base wants to call it. Then, since _originally_ the
pointer *was* to a member of 'Base', you're ok to use 'static_cast'.
If the pointer *never was* to a member of 'Base', casting is *not*
the right thing to do. You're correct suspecting that the behaviour
is undefined.
I think you've got it backwards. Pointer to member casts work
the opposite of normal pointer casts. There is an implicit D::*
to B::* conversion (no cast needed).
Nope. *You* got it backwards. Every member of 'B' is a member of
'D' as well (by inheritance), so 'B::*' =='D::*' requires no special
syntax, its implicit (modulo all the "available" and "unambiguou s"
cruft). [conv.mem]/2.
For the pointers to *objects*, however, it's reverse: Every 'D' is
a 'B' (modulo "available" and "unambiguou s"), so conversion from 'D*'
to 'B*' is implicit.
Yes. There's a mix of misunderstandin g what you wrote, and
mistyping what I wanted to say, there. What I wanted to say was
that the implicit conversions go in the opposite sense for
pointers to members, compared to pointers to objects (which you
just said in a lot clearer form), but that just like pointers to
objects, you can static_cast in the opposite sense of the
implicit conversion, *provided* the actual type is really a
derived; i.e. Base* -Derived* is legal if the object pointed
to by Base* is actually a Derived, and Derived::* to Base::* is
legal if the resulting pointer to member is only used with the
address of a Base which is actually a Derived.

So you were wrong concerning undefined behavior. But to be
quite frank, I also thought it was undefined until I ran into a
large code base which used it.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Sep 25 '07 #6
On Sep 21, 11:22 pm, Pete Becker <p...@versatile coding.comwrote :
On 2007-09-21 16:36:43 -0400, "Victor Bazarov" <v.Abaza...@com Acast.netsaid:
The static cast (as I understand it) would be called for
if you have a pointer to member of 'Base' ('Base::*ptr'), somehow
it was converted to a pointer to a member of 'Derived' ('Derived::*')
and then your base wants to call it. Then, since _originally_ the
pointer *was* to a member of 'Base', you're ok to use 'static_cast'.
If the pointer *never was* to a member of 'Base', casting is *not*
the right thing to do. You're correct suspecting that the behaviour
is undefined.
More generally, once you cast it, you have to cast it back to its
original type to get well-defined behavior.
Not really. Consider:

struct Base
{
virtual ~Base() {}
} ;

struct Derived1 : public Base
{
int i ;
} ;

struct Derived2 : public Base
{
double d ;
} ;

int Base::* pmi = static_cast< int Base::* >( &Derived1::i ) ;
Base* pd1 = new Derived1 ;
Base* pd2 = new Derived2 ;
pd1->*pmi = 42 ; // legal and well defined
pd2->*pmi = 42 ; // undefined behavior.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Sep 25 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

19
6877
by: Thomas Matthews | last post by:
Hi, Given a structure of pointers: struct Example_Struct { unsigned char * ptr_buffer; unsigned int * ptr_numbers; }; And a function that will accept the structure:
3
3457
by: ozbear | last post by:
This is probably an obvious question. I know that pointer comparisons are only defined if the two pointers point somewhere "into" the storage allocated to the same object, or if they are NULL, or one-past the end of the object as long as it isn't dereferenced. I use "object" in the standard 'C' sense. Is there some special dispensation given to comparing two pointers
13
2432
by: brian | last post by:
Quick question: if I have a structure: struct foo { unsigned char *packet; unsigned char *ip_src; };
47
2667
by: sunglo | last post by:
Some time a go, in a discussion here in comp.lang.c, I learnt that it's better not to use a (sometype **) where a (void **) is expected (using a cast). Part of the discussion boiled down to the rule: if I cast a (sometype **) to a (void **) I am making a number of assumptions about the implementation's (void **) representation and length. Specifically, if I do the above cast I'm assuming that a (sometype **) and a (void **) have the same...
3
1706
by: andy_dufresne | last post by:
have posted the question here: http://groups.google.com/group/programpara/browse_thread/thread/75b58c897f890930
20
2130
by: Joe Van Dyk | last post by:
Is there some rule of thumb about when to use pointers to an object and when to use a reference* to an object when a class needs to have objects as data members? Example: class A { B* b_ptr; B b; vector<B*> vector_ptrs;
18
11329
by: chankl | last post by:
Can anyone explain what's an opaque pointer and how it's implemented in C? I read about this concept in the book "C interfaces and implementations". Here's an example from the book (list.h - available from the website): #define T List_T
66
2725
by: Praveen | last post by:
Hi, I came across a program as follows main() { int x, y ; int *p1 = &x; int *p2 = &y; printf("%d\n", p1-p2); }
25
13062
by: J Caesar | last post by:
In C you can compare two pointers, p<q, as long as they come from the same array or the same malloc()ated block. Otherwise you can't. What I'd like to do is write a function int comparable(void *p, void *q) that will take any two pointers and decide whether they can be compared or not. I really can't think how to do this - any suggestions?
0
9680
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10230
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
10012
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9052
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7548
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6788
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
1
4118
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3731
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2926
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.