473,386 Members | 1,801 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

const problems with one class referencing another

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
3 1586
"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
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
>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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Jan13 | last post by:
Hi, I'm new to programming in C++ (using VC6) and ran into the following problem: I want to declare and define a class member variable as 'static const', but something seems to go wrong with...
12
by: Christof Krueger | last post by:
Hello, I'm quite new to C++ so maybe there's something I miss. I write a simple board game. It has a board class. This class has a method that returns the count of pieces a player has on the...
26
by: Michael Klatt | last post by:
I am trying to write an iterator for a std::set that allows the iterator target to be modified. Here is some relvant code: template <class Set> // Set is an instance of std::set<> class...
3
by: DanielBradley | last post by:
Hello all, I have recently been porting code from Linux to cygwin and came across a problem with static const class members (discussed below). I am seeking to determine whether I am programming...
4
by: Ant | last post by:
Hi, I'm having trouble trying to define the difference between declaring a field in a class const or static. i've noted that when referencing them from the class that a const is symbolized with...
6
by: WLT | last post by:
I'm keeping both a variable, and its default value in a class: class X { public const string DefaultString = "Default Value"; ... public string VarString = DefaultString; } I'm probably not...
0
by: Larry Lard | last post by:
This came out of a thread explaining to "BK" about error BC42025 ("Access of shared member through an instance; qualifying expression will not be evaluated"); Frans Clasener then came up with...
20
by: tshad | last post by:
Using VS 2003, I am trying to take a class that I created to create new variable types to handle nulls and track changes to standard variable types. This is for use with database variables. This...
12
by: hweekuan | last post by:
hi, it seems i can't assign the const variable u in class A, one way to solve the problem may be to build a copy constructor. however, why does C++ or vector class not like this code? my g++ is:...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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,...

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.