Static Polymorphism Issue - c++

I am on a micro controller (which means I can only have static memory allocation) and I am trying to work with inheritance.....
Suppose I have a abstract class Image and an abstract class Font. An instance of Font can return an Image based off of the char given in a function like so:
Font* mf;
Image* image = mf->GetImage("a");
Now the real issue is I have no idea what to do for the GetImage Function.
The problem is this: in c++ for you to have a member of an abstract class you have to use it as a pointer. So my dilemma is that I have a Font which wants to create a new Image and then return it.
If it returns a pointer to its newly created Image you are returning a reference to a temporary object:
Image* FontImpl::GetImage(char c){
return &ImageImpl(c); //This object is destroyed once this function exits
}
And then if I return I try to return an actual type like this:
Image FontImpl::GetImage(char c){
return ImageImpl(c); //Cannot cast from ImageImpl to Image
}
So is there an idiom or something for this kind of static memory problem?

Using dynamic allocation would be easiest but if that's not possible, you have to store the instance somewhere outside the function, e.g.:
static ImageImpl image;
Image& FontImpl::GetImage(char c) {
image = ImageImpl(c);
return image;
}

Related

Why declaring a QImage as static const produces an invalid value?

I have a QGraphicsItem object called ItemView which I am creating many instances of, and they all show up as a QImage on my QGraphicsView.
I have it working by creating a new QImage for each instance of ViewItem, but now I'm trying to convert that property to a static field to optimize because I really only need one, and I just cant get it to work.
As a test I added a static const int next to the QImage and that works just fine.
// .hh
class ViewItem : public QGraphicsItem
{
public:
...
private:
static const QImage IMAGE;
static const int TEST;
};
//.cc
const QImage ViewItem::IMAGE = QImage(":/data/data/img.png");
const int ViewItem::TEST = 30;
breakpoint in my QGraphicsItem::paint() method shows IMAGE value as (invalid) but TEST shows 30 as expected.
Why is it working for int but not QImage?
Note: For me this is a XY problem. I will provide a solution to the X problem and I suggest you to think about your Y problem and probably ask another question, which targets it explicitly.
Cause
You initialize ViewItem::IMAGE with a QImage, constructed from a fileName. As per documentation:
If the loading of the image failed, this object is a null image.
The loading fails, because the resource file is not available at the time, at which ViewItem::IMAGE is initialized.
Solution to X
To get the expected result, instead of a resource image, use an image from the disk, located in the data/data/ subfolder with respect to the build folder:
const QImage ViewItem::IMAGE = QImage("data/data/img.png");
The image would exist at the time of the initialization, so the constructor would succeed to create a valid QImage. To test this, call:
qDebug() << TEST << IMAGE;
in the constructor of ViewItem. It would produce a similar result:
30 QImage(QSize(256, 256),format=QImage::Format_ARGB32,depth=32,devicePixelRatio=1,bytesPerLine=1024,sizeInBytes=262144)

Error: Could not convert from sensor[] to sensor

I already have this class
class sensor : iElectronicParts{
// Some stuff here like methods and properties
};
For accessing all sensors I want to store them in a new object with type of global, so I just coded this class (there's no set method because I already ran into an error)
class global {
public:
sensor getSensors() {
return sensors; // This line throws the error
}
private:
sensor sensors[10];
};
and I got this error message
Compiling sketch...
/tmp/538691267/200119_Growbox/200119_Growbox.ino: In member function
'sensor global::getSensors()':
/tmp/538691267/200119_Growbox/200119_Growbox.ino:335:12: error: could
not convert '((global*)this)->global::sensors' from 'sensor [10]' to
'sensor'
return sensors;
^~~~~~~
exit status 1
I did not instantiated this object yet, I only defined the class. If I replace every type definition of sensor by int it works.
Could someone please tell me what I'm doing wrong / what I have to do to fix this?
You are storing an array of sensor in your class, but GetSensors is trying to return a copy of a single sensor. There's no conversion from an array to a single sensor, so your compiler doesn't know what it needs to do.
The question here is what you want to do: Do you want the whole list, or do you want to get a single sensor.
If You want to return the whole array.
C++ does not support arrays as return types. You will have to return a pointer to the first element in your array.
The code would look like this:
sensor* getSensors() {
return sensors;
}
and you would use it like this, assuming g is an instance of global:
sensor* sensors = g.getSensors();
Serial.print(sensors[3].value);
This code uses what is called array to pointer decay. Callers of your getSensors function will no longer know what the size of the array is, you have to make sure to not go over bounds! As this returns a pointer to the original sensors, any modifications that you do later to the returned pointer will affect the array in the instance of global.
If you want to return a specific sensor
You just need to change your getSensors function to take as an argument the index of the sensor that you care about. It would look like this:
sensor& getSensor(int index) {
return sensors[index];
}
This returns a reference to a specific sensor. As with the pointer case, changes to the returned sensor will affect the original array inside the instance of global (which I assume is the intent)
If you do not want to make modifications to the original array, you should return by value, and omit the & from the return type.
getSensors() function's return type is a mismatch. you should return a sensor object then have to choose one of the sensors[index] or change the return type to sensor pointer. however, I advice to use stl types (you do not have to but it is the best way) #divinas has inform me that no std::array in ardunio so this advice is not applicable:
#include <memory>
#include <array>
class iElectronicParts{};
class sensor : iElectronicParts{
// Some stuff here like methods and properties
};
class global {
public:
std::array<sensor, 10>& getSensors() {
return sensors;
}
private:
std::array<sensor, 10> sensors;
};
int main(){
return 0;
}

print pointer address of reference class

Code Summary:
Need to pass object of Camera From TestCamera.cpp to Test1.cpp.
I created a object of class into TestCamera.cpp
Now, I want to pass this to Test1, so I passed this to another object.
Anyhow I am getting error of "Camera*" into Test1.cpp .
I am new to CPP. Is it perfect way to pass another class & print it's pointer value?
TestCamera.cpp
Camera * cameraClient=static_cast<Camera *>();
(Test1 *)->captureImage(*cameraClient*);
Test1.cpp
int Test1::captureImage(const Camera* Cam) {
jint lResult;
jlong ad = (jlong)&Cam;
LOGI("Test1: pointer : APP: %ld",ad);
i am not getting your whole code, but just giving you hint that you are passing it wrong way..
you need to pass like this:
(Test1 *)->captureImage(cameraClient);
but, i doubt because you are not allocating memory to cameraClient.
below is extra advise, which is out of your question:
in C++, when you want to create an object of a class dynamically, then you need to allocate memory using new like below:
Camera * cameraClient= new Camera;
which instantiate class of Camera & then pass it to CaptureImage if Test1 class already instantiated..
The code snippet in TestCamera.cpp is not right, when you say that you are creating an object then you need to either use new operator or define an object as below
Camera * cameraClientPtr=new Camera; // For default constructor
Camera cameraClientObj;
The way you invoke method captureImage also not right. If you have Test1 pointer created using any of the aforementioned way then you invoke the method as below,
Test1Ptr->captureImage(cameraClientPtr);
Test1Obj.captureImage(&cameraClientObj);

OpenCV trackbar callback in C++ class

I have a question about how to define the callback for trackbars in OpenCV when working with classes in C++.
When I define my trackbar let's say in the constructor method of my .cpp class how can I define the callback?
I have been trying to work with function pointers but it doesn't work out. I guess I must be doing something very wrong :-)
This is my header file:
class SliderwithImage {
public:
SliderwithImage(void);
~SliderwithImage(void);
void sliderCallBack(int pos);
};
This is the implementation file:
#include "SliderwithImage.h"
void SliderwithImage::sliderCallBack(int pos) {
}
SliderwithImage::SliderwithImage(void) {
const char* windowName = "window";
int lowvalue =1;
namedWindow(windowName, CV_GUI_EXPANDED);
createTrackbar("mytrackbar", windowName, &lowvalue, 255, sliderCallBack);
}
SliderwithImage::~SliderwithImage(void) {
}
Obviously the createTrackbar method does not recognize sliderCallBack... I guess it's a problem of scope. But I am not sure how to solve this?
Any help would be appreciated.
Thank you very much.
The callback function must be static or global, but you can pass it a reference to an object you want to operate on (see this post on the OpenCV Users mailing list).
The createTrackbar method has a userdata parameter which is passed to the calling function. In C there is an undocumented cvCreateTrackbar2 method, defined in highgui_c.h, which has the same functionality:
CVAPI(int) cvCreateTrackbar2( const char* trackbar_name, const char* window_name,
int* value, int count, CvTrackbarCallback2 on_change,
void* userdata CV_DEFAULT(0));
These methods let you create a class with a static callback function that takes a pointer to an object of that class. You can create the trackbar like so:
cv:createTrackbar("Label", "Window" &variable, MAX_VAL, &MyClass::func, this);
The callback would look something like this:
void MyClass:func(int newValue, void * object) {
MyClass* myClass = (MyClass*) object;
// ...do stuff.
}
Note that you don't need to explicitly update the variable yourself as long as you provided a pointer to it when creating the trackbar (as above), but if you need to process it first I suggest you set it explicitly in the callback function.
You have to implement the callback function either as a global function or a static member function. To make it more OOP look, you might prefer to implement it as a static member function:)
I am using a different solution to obtain the slider value in a class variable (in my case to obtain chosen rotation angle of a live video stream). The int* value in the createTrackbar function is a public class variable which is then used within a loop (while the video is acquired, but this might messily work repeatedly redrawing a single image).
Not the best solution but it works for me.
cv::createTrackbar("Rotation Angle(deg)", "Preview", &rotationAngle,
alpha_slider_max, NULL);
for(;;)
{
int rotAngle = this -> rotationAngle;
cv::Mat frame;
cv::Mat rot_frame;
this -> capture >> frame;
rot_frame = rotateVideo (frame, rotAngle);
imshow("Preview", rot_frame);
if(cv::waitKey(30) >= 0) break;
}

was not declared in this scope

I am new in C++ and working on a project with QT. I created a header file called imageconvert.h which is as follow:
class ImageConvert
{
private:
IplImage *imgHeader;
uchar* newdata;
public:
ImageConvert();
~ImageConvert();
IplImage* QImage2IplImage(QImage *qimg);
QImage* IplImage2QImage(IplImage *iplImg);
};
also I defined those public methods in imageconvert.cpp file.
Now, I want to call QImage2IplImage and IplImage2QImage from other cpp file. So i include imageconvert.h in that CPP file and called those two functions.
it gives the the following errors:
error: 'QImage2IplImage' was not declared in this scope
error: 'IplImage2QImage' was not declared in this scope
Any help would be greatly appreciated.
The functions you've defined are member functions of the ImageConvert class. You need an instance of that class to be able to call them.
Something like:
ImageConvert ic;
ic.QImage2IplImage(your_QImage_object);
If you don't need state to do the conversion, you should make those helper functions static. Then you can call them with:
ImageConvert::QImage2IplImage(your_QImage_object);
without first creating an instance of ImageConvert. But please note that you will not be able to use imgHeader or newData in those static functions - they are member variables, only usable within an instance of that class.
You could also remove these functions from your class and put them in a namespace.
Your question...
How exactly do you call those functions? Given your ImageConverter class, this is how you should be doing it:
// First create a new converter
ImageConverter conv;
IplImage* ipl = conv.QImage2IplImage(qimg);
qimg = conv.IplImage2QImage(ipl);
... And some advice on using classes
Do you by any chance come from a Java or C# background? If so, you should know that in C++ you can also have free functions (that don't belong to any class). You should only use classes when you need to abstract a certain (real world) concept, and not simply as a way to group functions:
// image_converter.h
IplImage* QImage2IplImage(const QImage* qimg);
QImage* IplImage2QImage(const IplImage* iplImg);
// someother.cpp
IplImage* ipl = QImage2IplImage(qimg);
qimg = IplImage2QImage(ipl);
Notice I added const to the function parameters — it's a good thing to be const correct. Additionaly, you can group your functions in a namespace:
// image_converter.h
namespace converter
{
IplImage* QImage2IplImage(const QImage* qimg);
QImage* IplImage2QImage(const IplImage* iplImg);
}
// someother.cpp
IplImage* ipl = converter::QImage2IplImage(qimg);
qimg = converter::IplImage2QImage(ipl);