By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,962 Members | 1,776 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,962 IT Pros & Developers. It's quick & easy.

const problems with one class referencing another

P: n/a
Hi folks,

currently I'm writing image classes for easier handling of Intel's IPP library.

My idea is to have to different classes. One class that represents a complete
image and deals with all the memeory management stuff, and another class, that
is only a tile of the image. Let's call the first MemoryImage, and the second
ReferenceImage.

My code works well for creating non const and const reference images to a non
const memory image. Unfortunately, it doesn't work for const memory images.

The following code illustrates my problem. It's neither stylistically nor
functionally perfect (in fact it's neglecting the identical byte offsets
between consecutive images lines, even though the image widths might be
different.
class MemImage {

public:

// Create image.
MemImage(int width, int height) : m_data(0) {

// check dimensions and allocate aligned memory
}

// Get width of image.
int getWidth() const { return m_width; }

// Get height of image.
int getHeight() const { return m_height; }

// Get pointer to image data.
unsigned char* getData() { return m_data; }

// Get const pointer to image data.
const unsigned char* getData() const { return m_data; }

protected:

unsigned char * m_data;
int m_width;
int m_height;

}; // class MemImage
class RefImage {

public:

RefImage(MemImage &image, int x, int y, int width, int height)
: m_data(image.getData()+y*image.getWidth()+x), m_width(width), m_height(height)
{}

// Get pointer to image data.
unsigned char* getData() { return m_data; }

// Get const pointer to image data.
const unsigned char* getData() const { return m_data; }

protected:

unsigned char *m_data;
int m_width;
int m_height;

}; // class RefImage
With the example code above, its possible to do:

void f()
{
MemImage m(400,300);
RefImage r(m, 40, 30, 200, 150);
const RefImge c(m, 40, 30, 200, 150);
}

It's also possible to change image data of m through r.getData()

The code breaks with:
void g()
{
const MemImage m(400,300);
const RefImge c(m, 40, 30, 200, 150);
}

Changing the constructor of RefImage to

RefImage(const MemImage &image, int x, int y, int width, int height)
: m_data(image.getData()+y*image.getWidth()+x), m_width(width), m_height(height)
{}

fails due to the initialization of unsigned char m_data with a const unsigned char.

Changing the member m_data of RefImage to const unsigned char, the constructor works,
but it's no longer possible to have write access to non const MemImages via a RefImage.

Can anyone break this vicious circle?

Thanks in advance,

Torsten

Aug 10 '07 #1
Share this Question
Share on Google+
3 Replies


P: n/a
"Torsten Wiebesiek" <wi*******@tnt.uni-hannover.dewrote in message
news:f9**********@registered.motzarella.org...
Hi folks,

currently I'm writing image classes for easier handling of Intel's IPP
library.

My idea is to have to different classes. One class that represents a
complete
image and deals with all the memeory management stuff, and another class,
that
is only a tile of the image. Let's call the first MemoryImage, and the
second
ReferenceImage.

My code works well for creating non const and const reference images to a
non
const memory image. Unfortunately, it doesn't work for const memory
images.

The following code illustrates my problem. It's neither stylistically nor
functionally perfect (in fact it's neglecting the identical byte offsets
between consecutive images lines, even though the image widths might be
different.
class MemImage {

public:

// Create image.
MemImage(int width, int height) : m_data(0) {

// check dimensions and allocate aligned memory
}

// Get width of image.
int getWidth() const { return m_width; }

// Get height of image.
int getHeight() const { return m_height; }

// Get pointer to image data.
unsigned char* getData() { return m_data; }

// Get const pointer to image data.
const unsigned char* getData() const { return m_data; }

protected:

unsigned char * m_data;
int m_width;
int m_height;

}; // class MemImage
class RefImage {

public:

RefImage(MemImage &image, int x, int y, int width, int height)
: m_data(image.getData()+y*image.getWidth()+x), m_width(width),
m_height(height)
{}

// Get pointer to image data.
unsigned char* getData() { return m_data; }

// Get const pointer to image data.
const unsigned char* getData() const { return m_data; }

protected:

unsigned char *m_data;
int m_width;
int m_height;

}; // class RefImage
With the example code above, its possible to do:

void f()
{
MemImage m(400,300);
RefImage r(m, 40, 30, 200, 150);
const RefImge c(m, 40, 30, 200, 150);
}

It's also possible to change image data of m through r.getData()

The code breaks with:
void g()
{
const MemImage m(400,300);
const RefImge c(m, 40, 30, 200, 150);
I can get this to work with an extremly ugly constant cast.

const RefImage c(*(const_cast<MemImage*>( &m )), 40, 30, 200, 150);

I've been trying various things and can't figure it out. It seems that
because RefImage has an
unsigned char* and is trying to initialize it from a const unsigned char*
from unsigned char*.

The only thing I've found so far that works is making m_data public, and
initalizing with

RefImage(const MemImage &image, int x, int y, int width, int height)
: m_data(image.m_data+y*image.getWidth()+x), m_width(width),
m_height(height)
{}

}

Changing the constructor of RefImage to

RefImage(const MemImage &image, int x, int y, int width, int height)
: m_data(image.getData()+y*image.getWidth()+x), m_width(width),
m_height(height)
{}

fails due to the initialization of unsigned char m_data with a const
unsigned char.

Changing the member m_data of RefImage to const unsigned char, the
constructor works,
but it's no longer possible to have write access to non const MemImages
via a RefImage.

Can anyone break this vicious circle?

Thanks in advance,

Torsten

Aug 10 '07 #2

P: n/a
Hi!

Torsten Wiebesiek schrieb:
Can anyone break this vicious circle?
No. You have to create a ConstRefImage class. But you can inherit it.

struct ConstRefImage {
ConstRefImage(MemoryImage const& m, ...)
: constImage(m)
{ ... }
MemoryImage const& constImage;
... //some const member functions
};
struct RefImage : ConstRefImage {
RefImage(MemoryImage& m, ...)
: ConstRefImage(m) //cast to const
, image(m)
{ ... }
MemoryImage & image;
... //some non-const member functions
};

void foo(ConstRefImage const& image) { ... }
void bar()
{
MemoryImage m(...);
RefImage r(m, ...);
foo(r); //works
};

HTH

Some other advise: you can use std::vector instead of raw memory to
avoid memory management issues. The std::vector is required to allocate
continuous memory. So "&v[0]" will give you the pointer you need.
Getting raw memory management correct is not trivial and should be avoided.

Frank
Aug 10 '07 #3

P: n/a
>Can anyone break this vicious circle?
>
No. You have to create a ConstRefImage class. But you can inherit it.

struct ConstRefImage {
ConstRefImage(MemoryImage const& m, ...)
: constImage(m)
{ ... }
MemoryImage const& constImage;
... //some const member functions
};
struct RefImage : ConstRefImage {
RefImage(MemoryImage& m, ...)
: ConstRefImage(m) //cast to const
, image(m)
{ ... }
MemoryImage & image;
... //some non-const member functions
};

void foo(ConstRefImage const& image) { ... }
void bar()
{
MemoryImage m(...);
RefImage r(m, ...);
foo(r); //works
};
Frank, that was a very good hint. Thanks! :-)

I now have the following class hierarchy:

class ConstImage {...};
class Image : public virtual ConstImage {...};

class MemImage : public Image {...};

class ConstRefImage : public virtual ConstImage {...};
class RefImage : public ConstRefImage, public Image {...};

Virtual inheritance, because ConstImage is not abstract but
deals with height and width information. Seems to work.

Some other advise: you can use std::vector instead of raw memory to
avoid memory management issues. The std::vector is required to allocate
continuous memory. So "&v[0]" will give you the pointer you need.
Getting raw memory management correct is not trivial and should be avoided.
I'd love to, but I'm not sure, whether it's really allocating properly
alligned memory. Therefore, I use Intels IPP Memory allocation function:

Ipp<datatype>* ippiMalloc_<mod>(int width, int height, int* pStepBytes);

It's neither very nice nor very convenient, but, well, it's a speed optimized
C library. There are some design drawback, but at least it's very fast.
Regards,

Torsten
Aug 13 '07 #4

This discussion thread is closed

Replies have been disabled for this discussion.