|
First you don't put the word "class" in front when using a class, the compiler already knows what IDE_USBD & IDE_HCD are.
However the main problem is you can't forward declare a class and use it as a member
If you don't know these are forward declarations .. you are telling compiler you have a class IDE_USBD & IDE_HCD
class IDE_USBD;
class IDE_HCD;
The problem is it doesn't tell the compiler how big they are and so it can't size them to use as a member. So you need
at least the class data and prototypes to be above where you try and include them into another class
class IDE_USBD {
public:
int Hello(void);
};
class IDE_HCD {
};
class IDE_ILI9341
{
public:
IDE_HCD hcd;
IDE_USBD usbd;
};
int IDE_USBD::Hello(void) {
}
Now the second option is close to your original but it has advantages and disadvantages you need to weight up.
That is turn the entries to pointers to the classes. The compiler will be happy because it knows the size of a
pointer.
class IDE_USBD;
class IDE_HCD;
class IDE_ILI9341
{
public:
IDE_HCD* hcd;
IDE_USBD* usbd;
};
class IDE_USB {
};
class IDE_HCD {
};
The advantages are you can have the classes in whatever order you want. You can change the
class objects on the fly if you need or not even create instances of them if not required.
So you get a fair amount of flexibility.
The downside is you have to call the class functions by pointer hcd->function(blah blah)
from within your class. That makes the code ever so fractionally slower than the other.
We aren't talking very much and the flexibility sometimes makes it very attractive.
The big thing in this form is that class IDE_USB and IDE_USBD will not auto create (its
only a pointer after all). You need to make sure you manually create an instance of the
classes to the pointer in your constructor of IDE_ILI9341. So your constructor must contain
the two lines to actually create the classes to the pointers
hcd = new IDE_HCD ( );
usbd = new IDE_USB ( );
You should also dispose of them in IDE_ILI9341 destructor. As the construction used new it
becomes your responsibility to destroy them as they have no scope to auto dispose.
In vino veritas
modified 13-Oct-16 0:29am.
|
|
|
|
|
The reason for the different error messages when you have parentheses or not are down to what you are declaring (I've removed the "class" from in front of hcd and usbd to leave the relevant parts):
class IDE_USBD;
class IDE_HCD;
class IDE_ILI9341
{
public:
IDE_HCD hcd;
IDE_USBD usbd();
...
Here hcd doesn't have parentheses, so it is a member variable. The compiler needs to know the size of the IDE_HDC class to store the variable in the IDE_ILI9341 class, which is why you get the "incomplete type" error.
The usbd declaration does have parentheses, so it is a member function returning an instance of the IDE_USBD class. The compiler doesn't need to know the size of the IDE_USBD class in this case because it doesn't affect the amount of space taken up in the class by usbd . You will run into problems later when you try to use usbd as a variable though (because it isn't one).
|
|
|
|
|
Hi,
I am developing an app for mobile using C++, I am calling DownloadManager from Homectrl.CPP, Then came to my mind, which will one will efficient and object will be nullified.
What is the exact difference between
DownloadManager objDownloadManager;
and
DownloadManager *objDownloadManager;
Which one will be used?
Some good insight will be appreciated.
|
|
|
|
|
It makes no difference whether you are dealing with an object or a standard item like an int, float or double.
This form you have created the item type ... these all do the same
int i;
double d;
DownloadManager objDownloadManager;
This form you have created a POINTER TO THE ITEM ... it's most likely just 4 bytes (assuming 32bit compilation).
As we haven't set them to anything they are effectively undefined and could be pointing anywhere.
int* i;
double* d;
DownloadManager* objDownloadManager;
So they are vastly different and not something you should ever be confused about .. NOT EVER.
So if you like the second form is like the address to your house, the first form is your ACTUAL PHYSICAL house.
What you are doing is telling me that if I write text for the address of a house I can live in the text because
it's the same thing as a physical house and it's confusing to you.
You use the pointer form for the same reason you use a written address for you house. Its a bit tiresome and hard
to carry the whole house around just so people can send you mail. The alternative reason might be because your
house hasn't yet been built to carry around
In vino veritas
modified 11-Oct-16 11:56am.
|
|
|
|
|
|
Hi,
Some practical thinking:
Case 1. You declare 'DownloadManager' as a member of another class:
The object declaration (DownloadManager objDownloadManager) means, objDownloadManager has the same life time of your parent (the class in which you have declared it) class. But, pointer member means objDownloadManager will live even if his parent die.
Case 2. You declare 'DownloadManager' in a function:
The object gets destructed just after function scope. But the pointer declaration, can live until you delete it either inside or outside the function scope (provided you keep the address).
Thats all I know.
|
|
|
|
|
|
One other point to remember - if you declare a pointer to the object (the second declaration), you need to explicitly call the constructor and destructor. When declaring it as an instance (first declaration), the constructor is called automatically at the point of the declaration, and the destructor is called when it goes out of scope.
Cheers,
Mick
------------------------------------------------
It doesn't matter how often or hard you fall on your arse, eventually you'll roll over and land on your feet.
|
|
|
|
|
|
i am a C++ student and i was reading some source code and found this :
void FGAPIENTRY glutMenuStateFunc( FGCBMenuState callback )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" );
fgState.MenuStateCallback = callback;
}
in the code above , the return type is void and the function name is glutMenuStateFunc() .. what does FGAPIENTRY stand for and where dois it come from?? I've also seen some similar stuff wile reading a tutorial in win32 api
|
|
|
|
|
FGAPIENTRY is defined somewhere in your header chain (you have to look there to find it) as an attribute of the function.
On Window s code a similar define is often used to add dllexport/dllimport attribute to the same function, depending on the kind of build you are performing (the DLL itself or the application using the same DLL ). See, for instance c++ - Macro for dllexport/dllimport switch - Stack Overflow[^].
|
|
|
|
|
The FGAPIENTRY prefix is a macro that declares the calling convention for the generated code. It is similar to the WINAPI macro as described in Windows Data Types (Windows)[^].
|
|
|
|
|
Ratul Thakur wrote: ...what does FGAPIENTRY stand for... Look in your project's header files. It resolves to this.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
Here is the error from compiler I need assistance with deciphering.
I did try different type in the pointer declaration and it did just generated different errors.
I tried without specifying parameters - no char * - and obviously got different errors .
After removing the parameters from Process_INHERITANCE_A( Text); I got same error.
Help would be appreciated.
Thanks
Inheritance_A.h:27: error: void value not ignored as it ought to be
FunctionPointer_B = Process_INHERITANCE_A( Text);
Here is the stripped down code
void (*FunctionPointer_B)(char *);
class INHERITANCE_A : public INHERITANCE_B , public INHERITANCE_C
{
public:
void Process_INHERITANCE_A(char *Text);
};
bool INHERITANCE_A::TestFunctionPointer(char*Text)
{
FunctionPointer_B = Process_INHERITANCE_A( Text);
This is the only offending code line
return true;
}
void INHERITANCE_A::Process_INHERITANCE_A(char *Text)
{
}
^
|
|
|
|
|
You need to add the class declaration to the definition of the pointer, or make the function static.
See https://isocpp.org/wiki/faq/pointers-to-members[^].
[edit]
FunctionPointer_B = &INHERITANCE_A::Process_INHERITANCE_A;
FunctionPointer_B(Text);
modified 10-Oct-16 5:01am.
|
|
|
|
|
Richard,
setting the class function to static breaks calls from class A to class D , no biggie.
I need to fix this pointer first.
Adding class name to the funtion I wnat to point too got me this error:
cannot convert 'INHERITANCE_A::Process_INHERITANCE_A' from type 'void (INHERITANCE_A: ()' to type 'void (*)()'
Removing the function parameter - char* - created this error . I interpter iot as missing char.
// bool (*FunctionPointer_A)(void);
FunctionPointer_B = &INHERITANCE_A::Process_INHERITANCE_A; // (Text);
ketch/Inheritance_A.h: In static member function 'static bool INHERITANCE_A::TestFunctionPointer(char*)':
Inheritance_A.h:27: error: invalid conversion from 'void (*)(char*)' to 'void (*)()' [-fpermissive]
FunctionPointer_B = &INHERITANCE_A::Process_INHERITANCE_A; // (Text);
^
This is getting frustrating , but still this is only a test.
I am hoping to be able to have access from one class in inheritance chain to another member of the inheritance chain.
I do not like this dependencies / calls between the classes in the inheritance chain , but I kinda of inherited that. No pun intended.
I got it working going down the chain, now I need to go up the chain and hoping class pointers will work.
Sorry for this mess.
|
|
|
|
|
I can't for the love of me work out what you are trying to do but is this what you are trying to write
class INHERITANCE_B {
};
class INHERITANCE_C {
};
class INHERITANCE_A : public INHERITANCE_B, public INHERITANCE_C
{
public:
void Process_INHERITANCE_A(char *Text);
bool TestFunctionPointer(char*Text);
};
typedef void(INHERITANCE_A::*FunctionPointer_B)(char *);
bool INHERITANCE_A::TestFunctionPointer(char*Text)
{
FunctionPointer_B somePtr = &INHERITANCE_A::Process_INHERITANCE_A;
return true;
}
void INHERITANCE_A::Process_INHERITANCE_A(char *Text)
{
}
In vino veritas
modified 10-Oct-16 5:20am.
|
|
|
|
|
Sorry to butt in but your problem has nothing to do with classes or inheriting it's just code syntax that would not work anywhere.
Lets review function pointers ..
1.) you can set then to a function using the "&" symbol
2.) you can transfer the value to another function pointer that matches.
Can I suggest you first try and write just two function pointers in normal C++ and try to set them ... here let me write the code for you
void someFunc (char* text){
}
void(*FunctionPointer_A)(char *);
void(*FunctionPointer_B)(char *);
FunctionPointer_A = &someFunc;
FunctionPointer_B = &someFunc;
FunctionPointer_A = &someFunc;
FunctionPointer_B = FunctionPointer_A ;
I think this later is what you are attempting to do and if you copy the code in you should find it happily compiles.
Forgetting the class prefix this what you typed is nonsense .. it doesn't meet either of the item 1 or 2 formats
FunctionPointer_B = Process_INHERITANCE_A( Text);
After Richards suggestion you at least seem to get the function pointer setting
FunctionPointer_B = &INHERITANCE_A::Process_INHERITANCE_A;
That I can at least I can understand and is ever so close but now we come details of a class.
Any class function has a hidden self pointer pushed down on the function call. You don't see it the C++
compiler hides the syntax from you. So basically your function pointer doesnt equal the actual function
of a class function .. that is what the compiler is complaining about.
Your function pointer B needs to reflect its a class member function pointer .. not a function pointer to a static code
redefine it to
void(INHERITANCE_A::*FunctionPointer_B)(char *);
You may also need to typedef this if you want to carry the function as a forward declaration
All that is really happening is the function pointer knows to push the class self pointer down before it calls but from
your perspective it makes the compiler see the two as the same type.
There are better ways to do the function pointer assignment for classes, the magic term to do a search for is
memberfunctionpointer. Because you are trying to make a function pointer to a member function in a class.
Try:Member Function Pointers and the Fastest Possible C++ Delegates[^]
In vino veritas
modified 10-Oct-16 4:57am.
|
|
|
|
|
A nice clear explanation. 
|
|
|
|
|
I am still confused what he is trying to do. Why does he need the function pointer internal to the
class he can call any function from the inherited interfaces directly. You usually only do member
function calls from a block of code outside the class.
In vino veritas
|
|
|
|
|
Yes, I can't quite figure out what is (supposed to be) going on, and none of the code snippets make it any clearer.
|
|
|
|
|
Thanks, really helpful to make me understand how function pointer works.
The whole exercise is to be able to call from one class to another in the hierarchy.
What I am doing is recoding an app which was written without classes, I call it "flat" for lack of other words.
It is basically relations between embedded processor hardware devices - USB , USB host, UART ( print) , LCD and video camera ( USB device).
I am trying to use compound inheritance with top class managing the process of getting video data to the LCD.
It is interrupt driven and I think that is where I went wrong - I need to rebuild the inheritance relations to have the interrupt driven class as "mother ship".
I am pretty much done , the last piece is to actually process the video buffer.
That is where the function pointers are used.
Thanks again, you guys are very helpful and I appreciate that,
|
|
|
|
|
So the function call is from outside the class in the interrupt?
That will be fun trying to make sure the class in a stable running state not starting or closing, before you start passing interrupts into it. You will get a nice big crash if you pass an interrupt into the class and it isn't stable
In vino veritas
modified 10-Oct-16 10:42am.
|
|
|
|
|
The original code has ISR collecting the (video ) data and when it detects end of frame another function does the actual video output to the LCD.
I put the ISR code in one class and the output to LCD in another class.
Now both classes inherited from Print class so I can do code debugging etc.
There are other hardware inheritances - USB , SPI but that is all working.
That is how the compound inheritance came to be, and that is basically working.
The issue is the link between the ISR and LCD class.
I was hoping for another upper layer of class to be the controlling class, but that seems to be convoluted way to do it.
I think I have a better grasp on using function pointers and will try to just call from one class to another using pointers.
BTW the hardware interrupt is continuous and there are some checks in the actual interrupt handler and ISR functions making sure it is running and getting correct data / USB packages.
Thanks to the group I think I got the basics, now it is just a matter of organizing the puzzle.
|
|
|
|
|
What you have just said above is what makes what you are doing weird to us.
There is no need to inherit a print class just to print, you just hold a print
class instance in your class data and initialize it and you can print to it at
any time you need.
You don't inherit things just so you can use them. You only inherit things you
need to change the behaviour. Your class interface is just bloating up and
you gain exactly zero as you could already print what you need using the
original class.
So let me ask the specific question does your class change the print interface
it inherits in any way? If you answer no then you don't need to inherit it just
create an instance of the class in your class.
In vino veritas
|
|
|
|