Thread: forward class declarations

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    164

    forward class declarations

    I have a classes CElement and CSketcherView

    CSketcherView uses CElement, so I included a forward class declaration in the SketcherView.h file. (It just used there to define a pointer so it works with no hesitation)

    Now I want to know that, how the compiler locates the CElement's header file?

  2. #2
    Registered User
    Join Date
    Apr 2006
    Posts
    137
    Try using the
    Singleton Design Pattern for your classes that are needed in multiple files. (so you won't need forward class declaration)

    But if you are simply including one or two headers, just use
    Code:
    #ifndef __HEADERNAME__
    #define __HEADERNAME__
    
    
    class {
    
    };
    
    #endif
    So it can't be included multiple times.
    ★ Inferno provides Programming Tutorials in a variety of languages. Join our Programming Forums. ★

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by manzoor
    Now I want to know that, how the compiler locates the CElement's header file?
    It does not, since you did not include the file. What you did sounds correct: the class definition was not needed, so you just declared the class instead of including the header file that contains the class definition.

    Quote Originally Posted by execute
    Try using the
    Singleton Design Pattern for your classes that are needed in multiple files. (so you won't need forward class declaration)
    No, that is bad advice. The singleton design pattern has nothing to do with needing to use a class name in multiple files.

    Quote Originally Posted by execute
    But if you are simply including one or two headers, just use
    Incidentally, names that contain consecutive underscores are reserved to the implementation for any use.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Apr 2006
    Posts
    137
    Quote Originally Posted by laserlight View Post
    It does not, since you did not include the file. What you did sounds correct: the class definition was not needed, so you just declared the class instead of including the header file that contains the class definition.


    No, that is bad advice. The singleton design pattern has nothing to do with needing to use a class name in multiple files.


    Incidentally, names that contain consecutive underscores are reserved to the implementation for any use.
    Singleton, can be used for a class that's used in multiple files and multiple classes. It doesn't hurt, but I suppose it's overkill.

    By who, the C++ Deities? :P
    ★ Inferno provides Programming Tutorials in a variety of languages. Join our Programming Forums. ★

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by execute
    Singleton, can be used for a class that's used in multiple files and multiple classes. It doesn't hurt, but I suppose it's overkill.
    No, the singleton design pattern is used when you need at most one object of a class throughout the program. Here manzoor is talking about needing to use a CElement pointer. There is no evidence to suggest that at most one CElement object may exist.

    Quote Originally Posted by execute
    By who, the C++ Deities? :P
    In a way, if you consider the C++ standards committee the gods and goddesses of C++
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Apr 2006
    Posts
    137
    Quote Originally Posted by laserlight View Post
    No, the singleton design pattern is used when you need at most one object of a class throughout the program. Here manzoor is talking about needing to use a CElement pointer. There is no evidence to suggest that at most one CElement object may exist.


    In a way, if you consider the C++ standards committee the gods and goddesses of C++
    Yes, one object true, but it can also be used in cases where you need to access variables throughout a large project, without having multiple instances of it. In order to keep it simple.

    Though Singleton (as the name implies) is used in cases where we need to have one instance, it's not the only reason. Besides, I wasn't exactly understanding what the original poster wanted, he wasn't very clear, so I gave him options.


    Ok, so _HEADER_ and __CPP__ ?
    But how often do you ever #include, a .cpp anyway, imo, seems like a pretty useless standard :P.
    ★ Inferno provides Programming Tutorials in a variety of languages. Join our Programming Forums. ★

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by execute View Post
    Ok, so _HEADER_ and __CPP__ ?
    But how often do you ever #include, a .cpp anyway, imo, seems like a pretty useless standard :P.
    All names starting with _ and a capital is also reserved for the compiler. For example, the compiler already uses __LINE__, __FILE__, __DATE__ (I think) and various other __XXX__ names. Of coruse, if you have a "line.h" and you do "ifndef __LINE__ " it will not do anything, since __LINE__ is indeed defined by the compiler itself! So since you can't use this sort of name for SOME things, then you should not use it elsewhere either, because it becomes less consistent.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by execute
    Yes, one object true, but it can also be used in cases where you need to access variables throughout a large project, without having multiple instances of it. In order to keep it simple.
    If you do not actually need to control the number of objects created, then that sounds like an abuse of the singleton pattern such that some people have called it the "singleton anti-pattern". Effectively, you would just be using a global variable. Instead of keeping it simple, the tight coupling would merely make maintenance more difficult.

    Quote Originally Posted by execute
    Besides, I wasn't exactly understanding what the original poster wanted, he wasn't very clear, so I gave him options.
    Yeah, the question seems rather weird. manzoor basically asked how the compiler was supposed to find the header file, but the point is that the header file is not included since the forward declaration is used instead.

    Quote Originally Posted by execute
    Ok, so _HEADER_ and __CPP__ ?
    But how often do you ever #include, a .cpp anyway, imo, seems like a pretty useless standard :P.
    I think that you misinterpreted "implementation" to mean "source file". When the C++ Standard mentions "implementation", it means "compiler and standard library implementation", i.e., the names matching those conditions are reserved for use by C++ compiler writers and C++ standard library implementors.

    Oh, and the full clause is: "Each name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use."

    As such, you should also avoid defining the name _HEADER_, unless you happen to be writing a C++ compiler or standard library implementation.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Apr 2006
    Posts
    137
    Actually, you cannot define a global variable across multiple cpp files. It will give you redefinition errors. You may be able to do it, you'd have to be really careful. So for that sort of purpose, I either try not to use global variables, or worst case, I use singleton. And just because I don't use it as a "single object" as the primary purpose, doesn't mean it hurts anyone.

    Fair Enough on the __ stuff.
    ★ Inferno provides Programming Tutorials in a variety of languages. Join our Programming Forums. ★

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by execute
    Actually, you cannot define a global variable across multiple cpp files. It will give you redefinition errors. You may be able to do it, you'd have to be really careful.
    Ordinary global variables can be declared extern across header and source files and defined in exactly one source file.

    Quote Originally Posted by execute
    And just because I don't use it as a "single object" as the primary purpose, doesn't mean it hurts anyone.
    It hurts the maintainer because it makes maintenance more difficult, for the same reason that global variables make maintenance more difficult. If you are not making use of the power to limit instantiation that the singleton pattern provides, then all you have is a glorified global variable. Some critics go as far as to argue that the singleton pattern is always an anti-pattern because of its close relation to global variables.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Apr 2006
    Posts
    137
    I never thought of that...
    I use "extern" in importing functions from assembly into C... I guess I should have thought of it as a way to import other source file functions and global variables too.


    Well, I guess since you can just do
    extern void function();
    extern int global;

    Well then, I suppose you eliminated the singleton pattern... Oh and if we used struct's instead of classes, zomg, you eliminated C++. We can go backwards all the time. Just because there's a newer method of doing the same thing, doesn't make it bad :P.

    "anti-pattern" that's hilarious, singleton does have its purpose, one instance, only one time. I suppose you can use a bunch of functions. But then again you can use assembly to code everything as well.

    And I don't believe it hurts the maintainer, and I still cannot see where "global variables = bad" thing is coming from (it works great with interrupts), and the only downside is controlling the variables, but it's not a problem for seasoned programmers. Unless you are on an embedded system that is extremely low on memory, I don't see how "globals can be bad"... This is similar to the whole "making variables public is bad!", they exaggerate the downside. private, public, globals, are only made so that everything is easier to read, understand, and debug, not because it makes any difference to machine language.

    Sometimes people take "common practices" too far.
    ★ Inferno provides Programming Tutorials in a variety of languages. Join our Programming Forums. ★

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Globals are bad becuase it allows anything anywhere to use the variable, and if a variable is used a lot, it gets hard to know how and when it's used, and if you decide to change something related to that variable, it is more difficult than if it is a local variable that you can determine: Ok, it's only used here, here and here, so it is safe to do this. Global variables, on the other hand, may be used in MANY places, and it is much harder to know the relationships between their use, the functions that use it, and any change you plan to make in the global variable.

    Public data members in classes are a related situation: Any code that uses the member variable will have to be changed if you change anything about the member variable. Let's say you have
    Code:
    class circle
    {
       public:
          double diameter;
          double area();
          double circumference();
          circle(double xdiameter = 0.0) : diameter(xdiameter) {};
    };
    Now, our pointy-haired boss have, for some unexplainable reason, decided:
    1. We must change diameter to radius.
    2. We can not change the size of the class (because there is other code that we do not want to "disturb" by recompiling).

    If we had originally designed the class using getter/setter functions for diameter [1], we could hide the fact that we're now storing the radius, by simply multiplying by 2 in the getter, and dividing by 2 in the setter.

    You may think "well, that doesn't matter, lets just recompile all the code" - which is fine if it's your own little project you are working on. But what if you have sold your library of gemetric calculations to a big customer, then you do not want to tell them "well, I've got a new version that is much better, particularly the circle functions are better, because we store the radius instead of the diameter <note: This is a salesman speaking, so any change is better> - but you have to recompile all the code that uses the library to make use of it". Well, if they have thousand and thousands of lines of code, in several dozen applications, some of which are written by third parties, they may not want to do that, so they say "Nah, we'll just stick with our trusty old one, so we won't pay for the new version" - which means that you (or your company) don't get the money for the new version you've just spent the last four months developing.

    [1] Beware of inline functions: A previously compiled module that uses an inline function will just grab the data at the related address in the class - so it would get the radius instead of diameter. It's ok to use inline functions internally in the class itself, and for interfaces that absolutely won't change.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Well then, I suppose you eliminated the singleton pattern...
    O_o

    If you are only using the usual implementation strategy, 'some_class * some_class::get_shared_instance()', of the common singleton pattern as a means of controlling access to a non-unique instance of an object shared across a program you are not using the singleton pattern.

    I get so tired of arguing this, but it isn't the interface, the implementation, or the name by which you call a construct that makes it fit or unfit for a particular purpose. The fact that there is an absolutely unique instance of an object is what makes it a singleton; the rest are just details.

    If you don't need an absolutely unique instance of an object, you don't need a singleton. If no instance of an object is special in this way, you don't have a singleton. You just have a global instance of an object requiring an interface to access.

    Soma

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by execute
    Well then, I suppose you eliminated the singleton pattern.
    If a singleton is not required then the singleton pattern is not applicable to begin with.

    Quote Originally Posted by execute
    Oh and if we used struct's instead of classes, zomg, you eliminated C++.
    Of course, structs and classes are effectively the same, though the struct keyword is often conventionally reserved for POD structs.

    Quote Originally Posted by execute
    Just because there's a newer method of doing the same thing, doesn't make it bad :P.
    Just because there's a newer method of doing the same thing does not make it good. As phantomotap pointed out, you are not actually using the singleton pattern if you are not working with a singleton.

    Quote Originally Posted by execute
    "anti-pattern" that's hilarious, singleton does have its purpose, one instance, only one time.
    Yes, that is why I am willing to accept it as a genuine design pattern. If you want a more extreme viewpoint, read SINGLETON - the anti-pattern!

    Quote Originally Posted by execute
    And I don't believe it hurts the maintainer, and I still cannot see where "global variables = bad" thing is coming from (it works great with interrupts), and the only downside is controlling the variables, but it's not a problem for seasoned programmers.
    Related to matsp's explanation, global variables present another problem for seasoned programmers: it is more difficult to establish a proof of correctness for a program in the presence of global variables because global state can change in unexpected ways whenever a function is called. Unit testing also becomes more difficult since the various program units would be more tightly coupled.

    Quote Originally Posted by execute
    This is similar to the whole "making variables public is bad!", they exaggerate the downside. private, public, globals, are only made so that everything is easier to read, understand, and debug, not because it makes any difference to machine language.
    Precisely: these language constructs exist to help programmers write code that "is easier to read, understand, and debug". I find it ironic that you accuse me of "going backwards all the time" and pointing out that I "can use assembly to code everything as well" when you insist that constructs more suited to assembly language be used in C++ without due consideration.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    Registered User
    Join Date
    Apr 2006
    Posts
    137
    I'm not accusing anyone of going backwards, but you were saying that some argue Singleton is an "anti-pattern", and that just didn't make much sense.

    @matsp, yes I know why they do it, it's just that they teach it so religiously, that people think "hmm I need a getter and setter for these 10 variables in this one file project!"

    It should be emphasized that in team projects or large scale or medium scale projects, we shouldn't be making variables public, and/or using global variables when we can use local instead, or in databases, a singleton instead of a global extern.

    @phantom, you have totally misunderstood what's going on.
    1) Singleton has the ability to be one instance. It has the ability to be accessed across multiple files. Now I didn't think of using "extern" for that purpose, as I only use it when importing assembly functions.

    So let's say I was using a singleton called:
    CCommon::getInstance()->getDLL("c.dll");
    I would use it in multiple files. And I only need one instance.

    But laserlight was nice enough with extremely wise experience & expertise, that she recommended using "extern". So instead I could include "CCommon.h" and do:
    extern void getDLL(string dll);

    In let's say, 10 other files.

    Well that sort of made the whole Singleton approach unnecessary. I don't really need a CCommon class, since my common functions can be accessed in multiple files now.

    Having it as a singleton, doesn't do any damage, I am using one instance of it. So I was saying in a way, I could eliminate the singleton and do the same thing, and I can also do it with singleton, it's the same.
    ★ Inferno provides Programming Tutorials in a variety of languages. Join our Programming Forums. ★

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with FIFO QUEUE
    By jackfraust in forum C++ Programming
    Replies: 23
    Last Post: 04-03-2009, 08:17 AM
  2. class composition constructor question...
    By andrea72 in forum C++ Programming
    Replies: 3
    Last Post: 04-03-2008, 05:11 PM
  3. Forward Declaration of Class Members?
    By 691175002 in forum C++ Programming
    Replies: 3
    Last Post: 01-17-2008, 10:34 PM
  4. class errors
    By romeoz in forum C++ Programming
    Replies: 3
    Last Post: 09-16-2003, 07:57 PM