Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Arrays of derived objects

Reply
Thread Tools

Arrays of derived objects

 
 
Daniel T.
Guest
Posts: n/a
 
      03-20-2006
In article <rXATf.267$>,
"Jack" <> wrote:

> Thank you Daniel, that sounds like a good idea. If I provide only
> constructors that take a destructor function as a parameter, the user must
> provide one in order to use my Buffer class. Do you think the following code
> would be correct? Is it portable? Does memory alignment work in it?
>
> using namespace std;
> template<class T>
> class Buffer
> {
> public:
> Buffer(T* p, size_t ElemSize size_t ArraySize, void(*pfn)(T*)) :
> _p(ArraySize), _i(ElemSize), _pfn(pfn)
> {
> void* u=reinterpret_cast<void*>(p);
> for(size_t j=0;j<ArraySize;++j)
> {
> _p[j]=reinterpret_cast<T*>(u);
> u+=ElemSize;
> }
> }
> ~Buffer() { (*pfn)(&_p[0]); }
> T& operator[](size_t i) { return *_p[i]; }
> const T& operator[](size_t i) const { return *_p[i]; }
>
> private:
> vector<T*> _p;
> size_t _i;
> void(*_pfn)();
> };
>
> Regards,
>
> Jack


Please try to compile your code before posting...

But you are on to something. Here is your code corrected. What makes it
work is the templated constructor...

template < class Base >
class Buffer
{
Buffer( const Buffer& );
Buffer& operator=( const Buffer& );
public:
template < typename Derived >
Buffer( Derived* p, size_t ArraySize, void(*pfn)(void*) )
: _memory( p )
, _p( ArraySize )
, _pfn( pfn )
{
for ( int i = 0; i < ArraySize; ++i )
_p[i] = &p[i];
}
~Buffer() { (*_pfn)(_memory); }
Base& operator[](size_t i) { return *_p[i]; }
const Base& operator[](size_t i) const { return *_p[i]; }

private:
void* _memory;
vector<Base*> _p;
void(*_pfn)(void*);
};

void kill( void* p ) { }
void kill2( void* p ) {
B* b = reinterpret_cast<B*>( p );
delete [] b;
}

int main() {
B b[20];
Buffer<A> buf( &b[0], 20, &kill );
assert( &buf[0] == &b[0] );
assert( &buf[1] == &b[1] );

B* b2 = new B[5];
Buffer<A> buf2( b2, 5, &kill2 );
assert( &buf2[0] == &b2[0] );
assert( &buf2[1] == &b2[1] );

}

Your loosing some type safety though, and the Buffer has to maintain an
extra pointer per object over a more conventional approach.

Also, copying Buffers would be problematic, which is why I disable it.


--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
 
Reply With Quote
 
 
 
 
Jack
Guest
Posts: n/a
 
      03-20-2006

"Daniel T." wrote:

> Please try to compile your code before posting...


Yes, I am sorry about the syntax errors in my code. I don't have a compiler
in my mobile computer and I did not notice the bugs until I had already sent
the message.

> But you are on to something. Here is your code corrected. What makes it
> work is the templated constructor...


Yes, that's it. A suitable combination of templates and void*s does the
trick. In the constructor another template parameter is allowed because it
does not change the object type, so the object can still be passed into
functions in the library.

Thank you very much for this solution.

Jack

>
> template < class Base >
> class Buffer
> {
> Buffer( const Buffer& );
> Buffer& operator=( const Buffer& );
> public:
> template < typename Derived >
> Buffer( Derived* p, size_t ArraySize, void(*pfn)(void*) )
> : _memory( p )
> , _p( ArraySize )
> , _pfn( pfn )
> {
> for ( int i = 0; i < ArraySize; ++i )
> _p[i] = &p[i];
> }
> ~Buffer() { (*_pfn)(_memory); }
> Base& operator[](size_t i) { return *_p[i]; }
> const Base& operator[](size_t i) const { return *_p[i]; }
>
> private:
> void* _memory;
> vector<Base*> _p;
> void(*_pfn)(void*);
> };
>
> void kill( void* p ) { }
> void kill2( void* p ) {
> B* b = reinterpret_cast<B*>( p );
> delete [] b;
> }
>
> int main() {
> B b[20];
> Buffer<A> buf( &b[0], 20, &kill );
> assert( &buf[0] == &b[0] );
> assert( &buf[1] == &b[1] );
>
> B* b2 = new B[5];
> Buffer<A> buf2( b2, 5, &kill2 );
> assert( &buf2[0] == &b2[0] );
> assert( &buf2[1] == &b2[1] );
>
> }
>
> Your loosing some type safety though, and the Buffer has to maintain an
> extra pointer per object over a more conventional approach.
>
> Also, copying Buffers would be problematic, which is why I disable it.
>
>
> --
> Magic depends on tradition and belief. It does not welcome observation,
> nor does it profit by experiment. On the other hand, science is based
> on experience; it is open to correction by observation and experiment.



 
Reply With Quote
 
 
 
 
Jack
Guest
Posts: n/a
 
      03-22-2006
Hi again,

I began wondering whether it might be possible to code something like this:

template<class Derived>
void kill(void* p)
{
delete[] reinterpret_cast<Derived*>(p);
}

and then instantiate this template function and substitute its address into
the _pfn member of the Buffer class in the templated constructor when the
Derived type is known.

However, at least in MSVC++ 6 I didn't make it compile. Any ideas?

Regards,
Jack


 
Reply With Quote
 
Daniel T.
Guest
Posts: n/a
 
      03-22-2006
In article <Lb8Uf.110$>, "Jack" <>
wrote:

> Hi again,
>
> I began wondering whether it might be possible to code something like this:
>
> template<class Derived>
> void kill(void* p)
> {
> delete[] reinterpret_cast<Derived*>(p);
> }
>
> and then instantiate this template function and substitute its address into
> the _pfn member of the Buffer class in the templated constructor when the
> Derived type is known.
>
> However, at least in MSVC++ 6 I didn't make it compile. Any ideas?


As I showed in my sample code, your buffer class can't guarantee that
the array passed in was created with new[] so your Buffer can't assume
that delete[] is appropriate.

However, you can use the above kill function in the Buffer class I
already provided...

Buffer buf( new B[5], 5, &kill<B> );


--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
 
Reply With Quote
 
Jack
Guest
Posts: n/a
 
      03-22-2006
"Daniel T." wrote:

> As I showed in my sample code, your buffer class can't guarantee that
> the array passed in was created with new[] so your Buffer can't assume
> that delete[] is appropriate.


I can document that or provide another way to force the correct deallocation
function be used (for example, have different Buffer constructors for each
case or something). Anyway I would like to know whether it is possible to
have that functionality inside the Buffer class itself. By the way, do you
think it would be a good idea to replace the void*s by Base*s in the Buffer
class? Would it be better type safety or just misleading?

Jack


 
Reply With Quote
 
Daniel T.
Guest
Posts: n/a
 
      03-22-2006
In article <hVdUf.298$>, "Jack" <>
wrote:

> "Daniel T." wrote:
>
> > As I showed in my sample code, your buffer class can't guarantee that
> > the array passed in was created with new[] so your Buffer can't assume
> > that delete[] is appropriate.

>
> I can document that or provide another way to force the correct deallocation
> function be used (for example, have different Buffer constructors for each
> case or something). Anyway I would like to know whether it is possible to
> have that functionality inside the Buffer class itself.


Sure, just make the pointer assignment in the constructor body instead
of passing it in as a parameter.


> By the way, do you
> think it would be a good idea to replace the void*s by Base*s in the Buffer
> class? Would it be better type safety or just misleading?


That would be a bad idea because its undefined behavior.


--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Multidimensional arrays and arrays of arrays Philipp Java 21 01-20-2009 08:33 AM
Derived::Derived(const Base&) and Derived& operator=(const Base&) developereo@hotmail.com C++ 1 05-23-2007 01:44 PM
Derived::Derived(const Base&) developereo@hotmail.com C++ 4 05-23-2007 09:32 AM
Derived::Derived(const Base&) and Derived& operator=(const Base&) developereo@hotmail.com C++ 1 05-23-2007 12:07 AM
Arrays of derived objects - newbie Robert C++ 5 01-14-2007 12:13 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57