Topic: Encapsulating C struct
Author: WSEYMOUR@email.usps.gov
Date: 1997/03/25 Raw View
I'm writing a C++ function that gets called from
a shrink-wrapped library (presumably written in C)
and is passed a pointer to a structure. The library
function assumes that it is calling a C function.
I'd like to encapsulate the structure something like:
struct foo { ... }; // the library's structure
class bar : private foo
{
// non-virtual member functions only
private:
bar();
bar(const bar&);
bar& operator=(const bar&);
~bar();
static int static_member_object;
};
Is it safe and portable to write my function as:
void foobar(bar *bp) { ... }
when the argument is really a foo*? Is this essentially
the same question as whether it's safe to cast a foo*
down to a bar*? (Note that I'm careful not to add any
virtual member functions or non-static member objects;
and I can't construct, destruct or assign such an object.)
--Bill
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Stephen.Clamage@eng.sun.com (Steve Clamage)
Date: 1997/03/26 Raw View
In article @MHS, WSEYMOUR@email.usps.gov writes:
>I'm writing a C++ function that gets called from
>a shrink-wrapped library (presumably written in C)
>and is passed a pointer to a structure. The library
>function assumes that it is calling a C function.
>I'd like to encapsulate the structure something like:
>
> struct foo { ... }; // the library's structure
>
> class bar : private foo
> {
> // non-virtual member functions only
> private:
> bar();
> bar(const bar&);
> bar& operator=(const bar&);
> ~bar();
>
> static int static_member_object;
> };
>
>Is it safe and portable to write my function as:
>
> void foobar(bar *bp) { ... }
>
>when the argument is really a foo*? Is this essentially
>the same question as whether it's safe to cast a foo*
>down to a bar*? (Note that I'm careful not to add any
>virtual member functions or non-static member objects;
>and I can't construct, destruct or assign such an object.)
You are not assured this will work, although it is likely to
work with common implementations. The presence of a base class
removes any assurances about compatibility of bar and foo.
It is safer to derive the C++ class publicly from the C struct,
use the derived class in your C++ code and pass pointers to the base
class (an implicit conversion) to the C library. Example:
struct foo { ... }; // imported from the C header
extern "C" void f1(foo*); // C functions
extern "C" void f2(foo);
class bar : public foo {
// ... add whatever you want here
};
int main()
{
bar b;
f1(&b); // ok, implicit conversion to foo*
f2(b); // ok, "sliced" to a foo
}
I realize I'm answering the inverse of the question you asked.
For the question you actually asked, treating a foo as a bar, you
can add a constructor to bar that takes a foo reference or pointer.
Now you don't have to lie to the compiler or use unsafe casts, and
you can add to bar whatever features make it easier to use as a C++
class. (If you add data members, you run the risk of the C++ view
of the class becoming unsynchronized with the C view.) This approach
is not attractive if all the foo objects come from the C program,
since you wind up copying them when you create a bar.
If the foo objects are all created in the C program, you can define
class bar to have a reference member to a foo instead of deriving
from foo:
class bar {
public:
foo& thefoo; // or maybe make thefoo private
bar(foo& f) : thefoo(f) { ... }
... // whatever else
};
You can call the C functions as
f1(&b.thefoo);
f2(b.thefoo);
or you could overload the C functions with inline C++ wrapper functions
inline void f1(bar* b) { f1(&b->thefoo); }
inline void f2(bar& b) { f2(b.thefoo); }
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]