class is missing "type" - why ?
-
Never mind, instead of trying to find the bug in my code I am going to rebuild the classes, they need clean-up anyway. I have , so far , two relatively similar classes dealing with embedded processor hardware. Here is a code snippet, .... class IDE_USBD; class IDE_HCD; class IDE_ILI9341 { public: class IDE_HCD hcd; class IDE_USBD usbd(); .... If I do not include parenthesizes in implementation of class IDE_USBD I get this error IDE_ILI9341.h:371: error: field 'usbd' has incomplete type class IDE_USBD usbd; ^ exit status 1 field 'usbd' has incomplete type If I add them to class IDE_HCD hcd(); than I get this error: gpf_isr = hcd.UOTGHS_Handler; ^ IDE_ILI9341.h:2351: error: '((IDE_ILI9341*)this)->IDE_ILI9341::hcd' does not have class type hcd.HCD_Init(); ^ exit status 1 '((IDE_ILI9341*)this)->IDE_ILI9341::hcd' does not have class type Both classes have #include files before the IDE_ILI9341 gets implemented , I checked that. Now adding or removing parentheses makes it work, it ain't broke , but why are the parenthesizes needed for IDE_USBD? BTW that class has only default constructor implemented at this time. Help solving this puzzle will be appreciated. Cheers Vaclav
-
Never mind, instead of trying to find the bug in my code I am going to rebuild the classes, they need clean-up anyway. I have , so far , two relatively similar classes dealing with embedded processor hardware. Here is a code snippet, .... class IDE_USBD; class IDE_HCD; class IDE_ILI9341 { public: class IDE_HCD hcd; class IDE_USBD usbd(); .... If I do not include parenthesizes in implementation of class IDE_USBD I get this error IDE_ILI9341.h:371: error: field 'usbd' has incomplete type class IDE_USBD usbd; ^ exit status 1 field 'usbd' has incomplete type If I add them to class IDE_HCD hcd(); than I get this error: gpf_isr = hcd.UOTGHS_Handler; ^ IDE_ILI9341.h:2351: error: '((IDE_ILI9341*)this)->IDE_ILI9341::hcd' does not have class type hcd.HCD_Init(); ^ exit status 1 '((IDE_ILI9341*)this)->IDE_ILI9341::hcd' does not have class type Both classes have #include files before the IDE_ILI9341 gets implemented , I checked that. Now adding or removing parentheses makes it work, it ain't broke , but why are the parenthesizes needed for IDE_USBD? BTW that class has only default constructor implemented at this time. Help solving this puzzle will be appreciated. Cheers Vaclav
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 {
// ... this classes data and at least prototypes to functionspublic:
// lets do a prototype
int Hello(void);
};class IDE_HCD {
// ... this classes data and at least prototypes to functions
};// Class IDE_ILI9341 can now use the above two classes as the compiler can size them
class IDE_ILI9341
{
public:
IDE_HCD hcd;
IDE_USBD usbd;
};// we can put the code for IDE_USBD prototype down here
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 ( /* .. parameters it takes ..*/ );
usbd = new IDE_USB ( /* .. parameters it takes ..*/ );You should also dispose of them in IDE_ILI9341 destructor. As the construction used new it becomes your responsibilit
-
Never mind, instead of trying to find the bug in my code I am going to rebuild the classes, they need clean-up anyway. I have , so far , two relatively similar classes dealing with embedded processor hardware. Here is a code snippet, .... class IDE_USBD; class IDE_HCD; class IDE_ILI9341 { public: class IDE_HCD hcd; class IDE_USBD usbd(); .... If I do not include parenthesizes in implementation of class IDE_USBD I get this error IDE_ILI9341.h:371: error: field 'usbd' has incomplete type class IDE_USBD usbd; ^ exit status 1 field 'usbd' has incomplete type If I add them to class IDE_HCD hcd(); than I get this error: gpf_isr = hcd.UOTGHS_Handler; ^ IDE_ILI9341.h:2351: error: '((IDE_ILI9341*)this)->IDE_ILI9341::hcd' does not have class type hcd.HCD_Init(); ^ exit status 1 '((IDE_ILI9341*)this)->IDE_ILI9341::hcd' does not have class type Both classes have #include files before the IDE_ILI9341 gets implemented , I checked that. Now adding or removing parentheses makes it work, it ain't broke , but why are the parenthesizes needed for IDE_USBD? BTW that class has only default constructor implemented at this time. Help solving this puzzle will be appreciated. Cheers Vaclav
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
andusbd
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 theIDE_HDC
class to store the variable in theIDE_ILI9341
class, which is why you get the "incomplete type" error. Theusbd
declaration does have parentheses, so it is a member function returning an instance of theIDE_USBD
class. The compiler doesn't need to know the size of theIDE_USBD
class in this case because it doesn't affect the amount of space taken up in the class byusbd
. You will run into problems later when you try to useusbd
as a variable though (because it isn't one).