derive a class from a struct?

  • Thread starter Christopher Pisz
  • Start date
C

Christopher Pisz

This is a solution I thought about to some of the problems I had talked
about in the "zero memory" above in the ng.

While this isn't a MS specific post, let me walk you though the problem that
MS created that I am trying to overcome

They have functions:

HANDLE CreateIoCompletionPort(
HANDLE FileHandle,
HANDLE ExistingCompletionPort,
ULONG_PTR CompletionKey,
DWORD NumberOfConcurrentThreads
);

BOOL AcceptEx(
SOCKET sListenSocket,
SOCKET sAcceptSocket,
PVOID lpOutputBuffer,
DWORD dwReceiveDataLength,
DWORD dwLocalAddressLength,
DWORD dwRemoteAddressLength,
LPDWORD lpdwBytesReceived,
LPOVERLAPPED lpOverlapped
);

BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort,
LPDWORD lpNumberOfBytes,
PULONG_PTR lpCompletionKey,
LPOVERLAPPED* lpOverlapped,
DWORD dwMilliseconds
);

Now the flow of things that they show in thier example code creates a
context struct for each IO command, which contains user specific data. This
struct that they make contains an OVERLAPPED structure, which is what MS
uses to register an IO command with an IO-completion port. When the
IO-Completion port is done with an IO command, a thread stops waiting at a
call to GetQueuedCompletionStatus. Now then, when GetQueuedCompletionStatus
returns, all we have is the OVERLAPPED structure that was passed in as an
argument to the IO command, but we need the entire context. So, MS, in
thier example, casts the OVERLAPPED structure to the entrire structure that
it was a member of. This works because, they made the OVERLAPPED structure
the first member of the context structure.

I want to use C++, I am tired of mixing C code and C++ code together and
having to hack past the problems that arise.

In order to do this I was wondering if I could make a context class that is
derived from thier OVERLAPPED structure. That way I could dynamic cast from
an OVERLAPPED pointer to a context pointer right? That would get rid of
thier C cast that they depend on (which is really unsafe and is pretty much
a reinterp cast imo). I know I can cast from a base class upwards to a
derived class, can you also cast the other way around? Are there any inherit
problems with deriving a class from a struct that I need to know about? do
you think this solution would work?

Here is there OVERLAPPED for reference:

typedef struct _OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
};
PVOID Pointer;
};
HANDLE hEvent;
} OVERLAPPED,
*LPOVERLAPPED;
 
P

Pete Becker

Christopher said:
I want to use C++, I am tired of mixing C code and C++ code together and
having to hack past the problems that arise.

You're calling a C API, so you have to respect C conventions.
In order to do this I was wondering if I could make a context class that is
derived from thier OVERLAPPED structure. That way I could dynamic cast from
an OVERLAPPED pointer to a context pointer right?

No. If OVERLAPPED has any virtual functions (which is required in order
to use dynamic_cast), then it won't match the layout that the C function
you're calling expects. Even if it doesn't (which means you can't use
dynamic_cast), there's no guarantee that the compiler will lay out the
data in the same way it would when OVERLAPPED is the first member.
That would get rid of
thier C cast that they depend on (which is really unsafe and is pretty much
a reinterp cast imo).

Its behavior is well defined in both C and C++.

--

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

Victor Bazarov

I'm probably overquoting... Sorry about that. Don't have time to
trim it as needed.

Christopher said:
This is a solution I thought about to some of the problems I had
talked about in the "zero memory" above in the ng.

While this isn't a MS specific post, let me walk you though the
problem that MS created that I am trying to overcome

They have functions:

HANDLE CreateIoCompletionPort(
HANDLE FileHandle,
HANDLE ExistingCompletionPort,
ULONG_PTR CompletionKey,
DWORD NumberOfConcurrentThreads
);

BOOL AcceptEx(
SOCKET sListenSocket,
SOCKET sAcceptSocket,
PVOID lpOutputBuffer,
DWORD dwReceiveDataLength,
DWORD dwLocalAddressLength,
DWORD dwRemoteAddressLength,
LPDWORD lpdwBytesReceived,
LPOVERLAPPED lpOverlapped
);

BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort,
LPDWORD lpNumberOfBytes,
PULONG_PTR lpCompletionKey,
LPOVERLAPPED* lpOverlapped,
DWORD dwMilliseconds
);

Now the flow of things that they show in thier example code creates a
context struct for each IO command, which contains user specific
data. This struct that they make contains an OVERLAPPED structure,
which is what MS uses to register an IO command with an IO-completion
port. When the IO-Completion port is done with an IO command, a
thread stops waiting at a call to GetQueuedCompletionStatus. Now
then, when GetQueuedCompletionStatus returns, all we have is the
OVERLAPPED structure that was passed in as an argument to the IO command,
but we need the entire context. So, MS, in thier example,
casts the OVERLAPPED structure to the entrire structure that it was a
member of. This works because, they made the OVERLAPPED structure the
first member of the context structure.
I want to use C++, I am tired of mixing C code and C++ code together
and having to hack past the problems that arise.

In order to do this I was wondering if I could make a context class
that is derived from thier OVERLAPPED structure. That way I could
dynamic cast from an OVERLAPPED pointer to a context pointer right?

No. You can only use 'dynamic_cast' with polymorphic classes. Since
your OVERLAPPED struct is not polymorphic (and it can't be), you can
only use 'static_cast' if you are sure that the pointer you have is
in fact obtained by converting from a pointer to your derived class.
That would get rid of thier C cast that they depend on (which is
really unsafe and is pretty much a reinterp cast imo). I know I can
cast from a base class upwards to a derived class, can you also cast
the other way around?

Yes, but why?
Are there any inherit problems with deriving a
class from a struct that I need to know about?
No.

do you think this
solution would work?

It might.
Here is there OVERLAPPED for reference:

typedef struct _OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
};
PVOID Pointer;
};
HANDLE hEvent;
} OVERLAPPED,
*LPOVERLAPPED;

V
 
C

Christopher Pisz

Pete Becker said:
Its behavior is well defined in both C and C++.

--

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

Not to be a smartass, but more out of curiosity, where would I find such a
definition?
Does the same go for classes? Can you cast from a pointer to a class' first
data member, to a pointer to the entire class?
What if the class has virtual functions?

Thanks!
 
P

Pete Becker

Christopher said:
Not to be a smartass, but more out of curiosity, where would I find such a
definition?

In C99, 6.7.2.1/13. In C++, [class.mem]/18.
Does the same go for classes? Can you cast from a pointer to a class' first
data member, to a pointer to the entire class?
What if the class has virtual functions?

Only for POD-structs. But note that class and struct mean the same
thing, except for default access rules. So, yes, it goes for classes if
they satisfy the POD-struct requirements.

--

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top