Accessing an object from a different class - Design - c++

I have three classes, TImageProcessingEngine, TImage and TProcessing
TImageProcessingEngine is the one which i am using to expose all my methods to the world.
TImage is the one i plan to use generic image read and image write functions.
TProcessing contains methods that will perform imaging operations.
class TImageProcessingEngine
{
public:
TImage* mpImageProcessingEngine;
};
class TImage
{
public:
int ReadImage();
int WriteImage();
private:
//a two dimensional array holding the pixel values
tImageMatrix* mpImageMatrix;
};
class TProcessing
{
public:
int ConvertToBinary();
int ConvertToGrayScale();
};
My question is how do i access the object mpImageMatrix in class TProcessing? So that my calling application can use the following
TImageProcessingEngine* vEngine = new TImageProcessingEngine;
//Converts an input gray scsale image to binary image
vEngine->ReadImage().ConvertToBinary();
//Write the converted image to disk
vEngine->WriteImage();
delete vEngine;
vEngine = NULL;
//During this whole processing internally,
//the image is read in to `mpImageMatrix`
//and will also be holding the binarised image data,
//till writing the image to disk.
Or Do you recommend any other approach to my class design?

I would certainly recommend a different implementation, but let's check the design first.
I don't really understand the added value of TImageProcessingEngine, it doesn't bring any functionality.
My advice would be quite simple in fact:
Image class, to hold the values
Processing class (interface), to apply operations
Encoder and Decoder classes (interfaces), to read and write to different formats
It does make sense for the Processing class to have access to the images internal only if you can get efficiency from it (which is likely), in this case you can simply makes Processing friend and having it unpack the values for its derived
class Image
{
public:
Image();
void Accept(Processing& p);
void Encode(Encoder& e) const; // Image is not modified by encoding
void Decode(Decoder& d); // This actually resets the image content
private:
friend class Processing;
size_t mHeight;
size_t mWidth;
std::vector<Pixel> mPixels; // 2D array of Pixels
};
class Processing
{
public:
void apply(Image& image)
{
this->applyImpl(image.mHeight, image.mWidth, image.mPixels);
}
private:
virtual void applyImpl(size_t h, size_t w, std::vector<Pixel>& pixels) = 0;
};
Encoder and Decoder follow the same principle.
Note how I never needed an explicit pointer, and the guaranteed correctness that results from it.

First off, based on your provided code there are no ReadImage() & WriteImage() functions in the TImageProcessingEngine class, so the later code where you use such functionality is flawed.
As for the solution, you can make a getter function for the tImageMatrix pointer like this:
tImageMatrix* GetImageMatrix() { return mpImageMatrix; }
Then just pass that pointer (or a pointer to the whole TImage instance) to the TProcessing function you want to call.

Why you want to have a separate TProcessing process, when it specifically has functions just accessing mpImageMatrix;
In OOP, you have to bind the data members and it's operations..
So, IMO, remove your TProcessing class and have both the functions within TImage..
Your TImage will be like,
class TImage
{
public:
int ReadImage();
int WriteImage();
int ConvertToBinary();
int ConvertToGrayScale();
private:
//a two dimensional array holding the pixel values
tImageMatrix* mpImageMatrix;
};

You could create an accessor TImage class:
byte * pixelAt(unsigned x, unsigned y);

Related

How to call a function for specific objects in a C++ Array?

I hope you can help me because I'm trying to improve my C++ inheritance concepts. First of all, I have the following object hierarchy:
A base class "Image" with two child classes: PNG and JPG (each one with their methods).
I wrote a method inside PNG class which (in a simulated way) deletes alpha channel (it just prints "Alpha channel deleted").
That being said, I want to write a method which takes an array of many pointers to image objects (can be either JPG or PNG) as input, and deletes the alpha channel of only those which are PNG. Since it isn't a good practice in C++ ask for the type of the object (or so I believe), which is the best way to loop through the image array (remembering that it could be filled with either PNG or JPG objects) and delete the alpha channel of only the PNG objects? In which class should I write that method? Parent or child?
I hope I've explained myself correctly, and thank you very much in advance.
The obvious implementation is that the base class has a virtual method for deleting the alpha channel that is a no-op. The PNG class inherits from Image and overrides this member function.
class Image
{
public:
virtual void DeleteAlphaChannel() {};
};
class PNG : public Image
{
void DeleteAlphaChannel() override
{
cout << "Alpha Channel deleted" << endl;
}
};
Then a helper function that takes an array of Image pointers, hence Image**
void DeleteAlphaChannelsFromArrayOfObjects(Image** imageList, int count)
{
for (int i = 0; i < count; i++)
{
imageList[i]->DeleteAlphaChannel();
}
}
And corresponding sample code.
{
PNG pngFile("foo.png");
JPG jpgFile("bar.jpg");
Image* imageList[2] = {&pngFile, &jpgFile};
DeleteAlphaChannelsFromArrayOfObjects(imageList, 2);
}
You could also do a vector style implementation:
void DeleteAlphaChannelsFromArrayOfObjects(std::vector<Image*>& imageList)
{
for (Image* pImage : images)
pImage->DeleteAlphaChannel();
}

Access to a method of Object C in an Object B both created by Object A

I think the problem is quite basic and there was the same Question for sure somewhere here but i wasn't able to find.
So here is the Problem. Top has access to MyCircle and calls the SetSize function. But MyCircle has no access to MyRect.
I am able to access MyRect if i am providing a pointer to MyRect within the Constructor of MyCircle, but i think there should be another way. Maybe i just got it wrong at all :( Thanks for your help.
in the
class Top{
public:
Rect myRect;
Circle myCircle;
void Run();
};
class Rect{
public:
int size;
};
class Circle{
public:
int size;
void SetSize(int buffer);
};
void Circle::SetSize(int buffer){
myRect.Size = buffer;
}
void Top:Run(){
myCircle.SetSize(10);
}
Don't pass a rectangle to a circle class, the circle should have no knowledge about the rectangle (or vice versa).
Instead make a function in Top using both the circle and rect and act on that.
I don't know exactly what you want to do, but suppose you want to set the sizes equally. Than make e.g. a SetSize method in Top setting the sizes for both the circle and rectangle:
e.g.
class Top{
public:
Rect myRect;
Circle myCircle;
void Run();
void SetSize(int size)
}
where SetSize is implemented as:
myRect.SetSize(size);
myCircle.size = size;
It's always better to put code handling multiple derived objects in the base class instead of in one of the children. If there will be too much (or unrelated) functionality in the base class, create a different class (like SizeHandler).
btw, it's better not to use public properties but always get/set methods.

Updating data members of different derived classes of the same base class within a vector

I am writing a 3D gridded model in C++ which has different cell types, all stored within a vector that is in a Grid class. I have defined a base GridCell class and I also have two derived classes GridCell1 and GridCell2.
Now in setting up the model, I read in a text file that tells me how to fill my gridCell vector (std::vector<gridCell*> gridCellVector) in the Grid class; meaning it tells me what types of derived cells to push_back into my gridCellVector.
Then I read in another input file that contains initial state variable information for each GridCell in my Grid, in the order laid out by the 1st input file.
Each derived class (GridCell1 and GridCell2) has some state variables (private data members) that the other doesn't. How can I (or is it possible to) access and update/initialize/set the derived class' data members as I read in the second input file?
I've tried a couple different things and seem only able to return my get/set functions defined in the GridCell base class. I can't figure out how to access the functions in the derived classes when working with each derived GridCell as I step through the vector.
Edit: I am surprised people haven't mentioned downcasting, other than saying not to use dynamic_cast. I always know the type of GridCell I am updating because I keep track of what has been loaded into the vector when reading in the first input file. Since i am always certain of the type of GridCell, isn't dynamic_cast safe?
Double Edit:. Because I pass the GridCell objects to other functions that need to reference the data members and functions specific to the appropriate GridCell instance of the passed object, I'm realizing the design (of many parts) of my model does not currently pass muster. So, for now, I'm giving up on the idea of having to ride the GridCelltypes at all and will just create one huge GridCell class that fits all my needs. This way I can fill, and then access, whatever data members and functions I need later on down the line.
If you're sure you want to use a two-step process, I suggest you give GridCell a pure virtual init method:
virtual void init(istream &) = 0;
then implement it in each derived class. Its purpose is to read data from the file and initialize the initial state variables.
Single pass
As others have said, it may be best to read both files at once and do the derived class specific initialization at the same time as creating the derived classes:
std::unique_ptr<GridCell> createGridCell1(std::istream& init) {
auto cell = std::make_unique<GridCell1>();
int value;
init >> value;
cell->setGridCell1State(value);
return cell;
}
std::unique_ptr<GridCell> createGridCell2(std::istream& init) {
// similarly to CreateGridCell1()...
}
std::vector<GridCell::Ptr> createCells(std::istream& types, std::istream& init) {
std::vector<GridCell::Ptr> cells;
std::string type;
while (types >> type) {
if (type == "GridCell1")
cells.push_back(createGridCell1(init));
else
cells.push_back(createGridCell2(init));
}
return cells;
}
int main() {
auto types = std::istringstream("GridCell1 GridCell2 GridCell1 GridCell1");
auto init = std::istringstream("1 2.4 2 3");
auto cells = createCells(types, init);
for (auto& cell : cells)
cell->put();
}
Live demo.
Two pass with Visitor
If you must do the initialization in a second pass you could use the Visitor pattern. You have some sort of GridCellVisitor that knows how to visit all the different kinds of grid cells:
class GridCellVisitor {
protected:
~GridCellVisitor() = default;
public:
virtual void visit(GridCell1& cell) = 0;
virtual void visit(GridCell2& cell) = 0;
};
and your grid cells know how to accept a GridCellVisitor:
class GridCell1 : public GridCell {
int state = 0;
public:
void setGridCell1State(int value) { state = value; }
void accept(GridCellVisitor& visitor) override { visitor.visit(*this); }
};
class GridCell2 : public GridCell {
double state = 0.0;
public:
void setGridCell2State(double value) { state = value; }
void accept(GridCellVisitor& visitor) override { visitor.visit(*this); }
};
This way you can separate the responsibility of initializing the grid cells with an input stream from the grid cells themselves and avoid having to do fragile downcasts on the grid cells:
class GridCellStreamInitializer : public GridCellVisitor {
std::istream* in;
public:
GridCellStreamInitializer(std::istream& in) : in(&in){}
void visit(GridCell1& cell) override {
int value;
*in >> value;
cell.setGridCell1State(value);
}
void visit(GridCell2& cell) override {
double value;
*in >> value;
cell.setGridCell2State(value);
}
};
int main() {
auto in = std::istringstream("GridCell1 GridCell2 GridCell1 GridCell1");
auto cells = createCells(in);
auto init = std::istringstream("1 2.4 2 3");
auto streamInitializer = GridCellStreamInitializer(init);
for (auto& cell : cells)
cell->accept(streamInitializer);
}
Live demo.
The downside is GridCellVisitor must be aware of all different kinds of grid cells so if you add a new type of grid cell you have to update the visitor. But as I understand it your code that reads the initialization file must be aware of all the different kinds of grid cells anyway.
Your vector<gridCell*> knows only the base class of its elements and can hence only call gridCell functions.
I understand that your approach, is to first fill the vector with pointer to cells of the correct derived type, and never the base type. Then for each cell, you read class dependent data.
The easiest way, if you don't want to change approach
The cleanest way would be to define a virtual load function in the base cell:
class gridCell {
...
virtual bool load (ifstream &ifs) {
// load the common data of all gridCells and derivates
return ifs.good();
}
};
The virtual function would be overriden by teh derived cells:
class gridCell1 : public gridCell {
...
bool load (ifstream &ifs) override {
if (gridCell::load(ifs)) { // first load the common part
// load the derivate specific data
}
return ifs.good();
}
};
Finally, you can write your container loading function:
class Grid {
...
bool load (ifstream &ifs) {
for (auto x:gridCellVector)
if (!x->load(ifs))
break; // error ? premature end of file ? ...
}
};
The cleanest way ?
Your problem looks very much like a serialisation problem. You load grids, may be you write grids as well ? If you control the file format, and perform the creation and loading of the cells in a single pass, then you don't need to reinvent the wheel and could opt for a serialisation library, like boost::serialization.

Child classes that share Parent class member

I have an awkward question. I think it's impossible but I need to know for sure. It's a bit of an odd request, but I need my child classes to share the SAME Pixels vector from the parent class.
Basically, I want to create an instance of Image class. That Image class will hold Pixels for both Bitmap and Png Class so that if I need to convert from Bitmap To PNG and Vice-versa, they use the same vector rather than me creating both Bitmap and PNG classes.
class Image
{
private:
std::vector<RGB> Pixels;
};
class Bitmap : Image
{
public:
Bitmap() : Image() {};
};
class Png : Image
{
public:
Png() : Image() {};
};
Such that when I do:
int main()
{
Image Img();
Img.GetBitmapPixels(); //This
Img.GetPngPixels(); //And this, return the same Pixels Vector.
Bitmap Foo = Img.ToPng();
Png Moo = Img.ToBitmap();
//Such that both Foo and Moo have the exact same underlying Pixels Vector.
}
Currently my classes look like:
class Bitmap
{
private:
std::vector<RGB> Pixels;
public:
Bitmap();
std::vector<RGB> GetPixels() {return Pixels;}
void SetPixels(std::vector<RGB> Pixels) {this->Pixels = Pixels;}
};
class Png
{
private:
std::vector<RGB> Pixels;
public:
Png();
std::vector<RGB> GetPixels() {return Pixels;}
void SetPixels(std::vector<RGB> Pixels) {this->Pixels = Pixels;}
};
And to convert from one to the other, I have to do:
int main()
{
Bitmap Bmp();
Png PNG();
PNG.SetPixels(BMP.GetPixels); //BMP has to COPY PNG's Pixels and vice-versa..
}
It's kind of a stupid question. I just don't want to copy pixels. I just want to be able to convert between the two classes without any copying as both classes hold an std::vector Pixels member and the data is aligned the same.
I guess I'm trying to be able to do: PNG.SaveAsBitmap(...); Or BMP.SaveAsPNG(...); without creating a new instance of the other.
How can I avoid copying/creating and making a new instance of the other class I'm converting to? Can I have classes that inherit from eachother?
I may be oversimplyfying this. How are you loading your data? If it is the same for each image type could you have a load in the image class and just overload the Translation functions. I am not an expert on image data but could you do something similiar to:
public Image
{
private Pixels data;
public void GetPixels();
public virtual Pixels ToFormat(FormatEnum format);
}
public Bitmap:Image
{
public override Pixels ToFormat(FormatEnum format)
{
switch(format){
case FormatEnum.Bitmap:return data;break;
case FormatEnum.Png:return doSomethingElse();break;
}
}
}
int main()
{
Image Img();
Img.GetPixels();
Bitmap Foo = Img.ToFormat(Format.BitMap);
Png Moo = Img.ToFormat(Format.Png);
}
Since they share a parent as a common factor, you can elect to use pointers (this is considered a shallow copy), but this is usually not wise a deep copy is usually better. Perhaps you can create two functions one to create a shallow copy and one for a deep copy. Since a Bitmap and a Png are separate entities (they are siblings). Perhaps you should allow BMP to be the parent of png?
You may also elect to decouple the encoding altogether for saving purposes and just deal with the raw image data.

Design suggestions for an Image class hierarchy

I need some design suggestions for an Image class hierarchy.
Currently, I have 2 types of images (one is a standard image, the second doesn't contain standard image data).
Sometimes I want the object to allocate the memory for the image data, and other times I just want it to point to it.
The problem arises when I want to give TypeA images specific functionality.
If TypeA images inherit from Image, I will have to duplicate the functionality of the Allocated vs. non-Allocated Image.
I'm sure there is a better way to do this, I remember some elegant solutions with mixins during university, but can't find a way to use that here.
My current design looks like:
class Image
{
public:
Image(int width, int height, int bpp);
virtual ~Image() {};
// getters
template <typename T>
T* ptr() { return reinterpret_cast<T*>(m_imageData); } // T depends on bpp
protected:
// metadata
char* m_imageData;
};
class AllocImage : public Image
{
public:
AllocImage(int width, int height, int bpp, DataType dataType) :
Image(width, height, bpp, dataType)
{
m_imageData = new char[m_dataSize];
}
~AllocImage()
{
delete m_imageData;
}
};
class ImageHolder : public Image
{
public:
ImageHolder(int width, int height, int bpp, DataType m_dataType);
void setPtr(const void* ptr);
};
class AllocatedImageTypeA : public AllocImage
{
public:
// Type A specific methods
};
class NonAllocatedImageTypeA : public ImageHolder
{
public:
// duplicated Type A specific methods
};
If all the differences are constrained to how the image is held (allocated or not), you could use the policy model.
The short explanation is that you would pass a policy object to the image, where the policy describes whether you need to deallocate the image or not, how to access it, etc., basically anything that relates to the differences that arise from how the image data is held (allocated vs. pointed). Then all your access to the image will be through the policy.
For example, instead of writing
delete image;
You would write:
policy.del(image);
Where policy.del can be a delegate to delete or a no-op, depending on the actual type of the policy (that is in line with what the image requires)
Why so many types? If the difference is only in allocation, then simply create multiple constructors, one which takes a pointer to a pre-allocated data holder, one that doesn't and does the allocation internally. You could also use dependency injection to get the variations in behaviour / functionality.
I had a similar case.
Let's make something clear. Your class hierarchy its not based if an image is allocated or not, but, each class will have some features.
You may want to have a very specialized class that allocates images, another that references, and, warp that class with another of the same hierarchy, with similar features.
The following example, explains the idea of wraping one class, with another class,
from the same inheritance, that seems to apply to your questio.
Disclaimer: Please ignore, some minor bugs or non relevant syntax errors:
// generic base class for my image library:
/* abstract */ class GenericImage
{
public:
int width;
int height;
public:
/* constructor */ GenericImage() ;
/* destructor */ ~GenericImage() ;
/* constructor */ GenericImage(int newwidth, int newheight);
}; // class GenericImage
// in charge of allocating or deallocating an image
class AllocatedImage: GenericImage
{
public:
/* constructor */ AllocatedImage() ;
/* destructor */ ~AllocatedImage() ;
/* constructor */ AllocatedImage(int newwidth, int newheight);
/* constructor */ AllocatedImage(char* filename);
}; // class AllocatedImage
// access an image, but doesn't allocate or deallocate
class ContainedImage: GenericImage
{
public:
/* constructor */ ContainedImage() ;
/* destructor */ ~ContainedImage() ;
/* constructor */ ContainedImage(int newwidth, int newheight);
}; // class AllocatedImage
// real working class, will allocate other objects,
// of same hierarchy
class WrapperImage: GenericImage
{
public:
GenericImage* RealImage;
public:
/* constructor */ GenericImage() ;
/* destructor */ ~GenericImage() ;
void AllocateImage(AllocatedImage* newimage);
void HoldImage(ContainedImage* newimage);
}; // class AllocatedImage
Suggestions:
Its good idea, to have a constructor without parameters, specially if you are designing a class hierarchy, instead of a single class.
I know its a quick example, but, you may want to move all code to body file.
Cheers.