class declaration

I have predeclared a class like this

class PortConnection;

then i declare and define a class

class PortWriter {};

this class uses an instance of PortConnection.

later i define the class

class PortConnection {};

which instantiates a writer to the port after a successful connection.

However, i receive a compilation of type

Error 1 error C2027: use of undefined type 'bluecard::ioport::PortConnection'

what can be the problem?

both classes are in the same namespace bluecard::ioport

someone help


PortConnection must be an include dependency of PortWriter.

Obligatory link: http://cplusplus.com/forum/articles/10627/#msg49679 (see section 4: The "right way" to include)

It's hard to say for sure without seeing the code, but it sounds like you need portwriter.h to #include portconnection.h instead of just forward declaring PortConnection.
...reading Disch's link...

I could swear you need a forward declaration for "friend". The fact that you wrote "friend class MyFriend;" actually demonstrates this, as it is a friend declaration plus a forward declaration of "MyFriend".

You can "inline" any forward declaration, like:

 
void foo( class bar& ); // "bar" doesn't need to be forward declarated. But it is now. (as a "class") 



Another note: I would relax the right-way-of-include rule for one more case: some templates are typed in a way which include private and implementation defined behaviour in their type (as type parameter - see "policy template idiom"). The most famous example may be std::string, which is allowed to have additional template arguments specific to the compiler vedor (as all other STL container). Hence, you can't possible forward-declare them correctly without making implementation specific assumptions. This requires you to include some header. (Sometimes, the vendor provides a forward-declaration-only header file as "iosfwd" but not always - as std::string doesn't have one)

And there are another circumstances when you need a full include, for example the sizeof - operator ;-)


Then again, you get my full ACK for your item 5 ;). Especially about all those mislead souls who argue that there must not be any #include in any .h. :-D.

A good rule of thumb for me has been: The first statement in all of your CPP files is #include "corresponding_header.h" (Well, the second if you use precompiled headers. Just after the #include "stdafx.h"). This way gives a quite good insurance that you don't use types without including them first.

Ciao, Imi.
I could swear you need a forward declaration for "friend". The fact that you wrote "friend class MyFriend;" actually demonstrates this, as it is a friend declaration plus a forward declaration of "MyFriend".


That's a great point. I didn't even realize I was doing that.

Another note: I would relax the right-way-of-include rule for one more case: some templates are typed in a way which include private and implementation defined behaviour in their type


I thought of this a few weeks after I my last edit in that thread. I think the way to phrase it would be to #include things in foreign libraries that you cannot have a dependece on your code.

For example, if you write a class MyClass, you know that std::string can't possibly have MyClass as a dependency, and therefore it's ok to #include.

Then again, you get my full ACK for your item 5 ;)


ACK as in you don't approve? XD

I try to be impartial, but I tend to get a little carried away with bias sometimes.


Another thing I thought of mentioning were "group header" (ie: header files that just include other, related headers)

I also thought about rewriting it and submitting it as an actual article on the site rather than a forum post. But I just can't find the time and/or don't have the patience.
I thought of this a few weeks after I my last edit in that thread. I think the way to phrase it would be to #include things in foreign libraries that you cannot have a dependece on your code.

For example, if you write a class MyClass, you know that std::string can't possibly have MyClass as a dependency, and therefore it's ok to #include.


If its in a foreign library, how could it possible depend on your code in terms of compile-dependency? I mean.. it is already compiled! ;-)

Anyway, the rules I've seen about when to include/forward declare stuff from foreign libraries vary as much as the definition of "foreign library".

But I got the point. Maybe std::string is not a good example as there are good reasons to even include string already in your precompiled header. ;)

Let me make another example of an "type that contains implementation defined behaviour":
1
2
3
4
5
#ifdef NDEBUG
typedef _fast_file_allocator FileAllocator;
#else
typedef _debug_file_allocator FileAllocator;
#endif 


I hope you agree with me that it's not a good idea to try to forward-declare FileAllocator every time "by hand"? That's also because the actual type of FileAllocator depends on some other attributes (as whether NDEBUG is defined or not). My recommendation is, to provide a forward-declaring header file for all people who need correct forward declarations of FileAllocator.
1
2
3
4
5
6
7
8
// FileAllocatorFwd.h
#ifdef NDEBUG
class _fast_file_allocator;
typedef _fast_file_allocator FileAllocator;
#else
class _debug_file_allocator;
typedef _debug_file_allocator FileAllocator;
#endif 


If there is no such forward-declaring header, it's probably better to include the original header than to copy'n'paste the #ifdef with those ugly class names around into every header file who only uses file allocator pointer.


Hm... while writing this, I recognized that actually I am only suggesting, that "forward declarations" sometimes mean "include an other header file than the one with the complete declaration that has a forward declaration inside".


ACK as in you don't approve? XD

Huh? Actually ACK as in "I approve this" :-D

You are writing about the fact, that a header should always include enough so that anyone including it is never forced to include something else before to make it compile. That's what I think too. Many people suggest that they should include that absolute minimum (which means: Nothing), even if this means users are forced to include files before this header to make it compile. This is wrong thought, as it doesn't remove dependencies but only shift them around and lead to include-order-hell and hidden circular references.

Ciao, Imi.
Last edited on
Great points all around, imi. I pretty much agree with you 100%. I wish that other thread wasn't archived so I could modify it =( Oh well.

Huh? Actually ACK as in "I approve this" :-D


Heh. I've never seen it used like that before. Is that an acronym for something?

I thought you were like saying "Ack!" like a shriek after seeing something terrible XD. As wikipedia describes it: "Ack is a common exclamation, of general or unwanted surprise"
Actually both classes are in the same header files, bcioport.h.
What i intend to do is that, a client can only instantiate a the PortConnection and then from the PortConnection instance, retrieves a writer to the port. This writer is implicitly managed by the PortConnection object. I do this because i want to maintain some form of synchronization to the port since i am using an OVERLAPPED connection.

As a matter of caution, i pre-declared both classes;

class PortConnection;
class PortWriter;

then i implemented the Writer class first, which requires a pointer to the PortConnection
and then implement PortConnection which will instantiate a writer and returns a pointer to it.
Heh. I've never seen it used like that before. Is that an acronym for something?


It's the shortcut for "Acknowledgment" and got mostly famous in combination with the TCP/IP definition of sending a SYN and receiving the ACK as response. Some other formats uses "ACK" as acknowledgment now too, e.g. the german health care protocol (HL7) has a mode where it sends as acknowledgemtn only 3 ASCII-leters to the sender: ACK ;)

then i implemented the Writer class first, which requires a pointer to the PortConnection
and then implement PortConnection which will instantiate a writer and returns a pointer to it.

Then it seems, you have something in your PortWriter, what needs a more than just the forward declared pointer. Can you post the line where the error occured (and some lines before and after)?

Ciao, Imi.
Topic archived. No new replies allowed.