sofla

Members
  • Content count

    28
  • Joined

  • Last visited

Community Reputation

117 Neutral

About sofla

  • Rank
    Member
  1. If you can't wait for c++2011 and you are using a somewhat recent gcc or msvc, they both have hashtables as part of the library. The interfaces are even mostly compatible with each other. If you don't want STL then roll your own. Most libraries will have "overhead" in the sense that it will have features that you don't intend to use. Eventually you will get bored with writing your Nth inefficient list or hash you will start using canned libraries (ex: STL) like everyone else. Sure once in awhile you will have a "hot" data structure that warrants a handcrafted data structure but that is usually not the case.
  2. I prefer one step initialization. Unless you have a thing for extra typing when creating objects. Also, I find that one-step initialization tends to make you think more about object graph / dependencies, and so you are less likely to end up with co-dependent / mutually dependent objects and order-of-initialization problems. The issue of how to handle initialization failure (exception or flag or something else) is completely independent of whether or not you do one/two step init. A constructor can flag invalid? or throw and so can ::initialize(). Error handling is important but for this particular topic it is a red herring issue. The only practical consideration here that I can think of (besides extra typing) is whether or not you want to be able to put your object (and not a pointer to it) into STL or similar containers. Many/most containers require that your object have a no-argument constructor. If a no-arg constructor makes sense and you want to put the object into a container, then one-step is much more practical. If you aren't sure, write a separate ::initialize method and have your ctor call it. Be sure to do the right thing if ::initialize() is called twice. If the object in question lends itself to object pooling, then you'll want ::initialize(), ::reinitialize(), ::clear() or similar so that you can tidy it up before you put it back in the pool. Speaking of pooling (I realize this is going a bit off topic), if you think you are likely to end up with pooling then make all your ctor's private and use a static class method to get an object instance.
  3. Quote:Original post by random_thinker Quote: Is it asked to much that I just want to compile my code into a single .exe file that will run on every PC? Personally, I find that the Eclipse IDE combined with GCC G++ allows me to use C++ Std Library-compliant code on just about any operating system I need. I presently use OSX, WinXP (trying Vista soon) and Linux (32 and 64 bit architectures). Linux 64 bit is my main development platform. IMHO, it is possible to write once and use on multiple platforms in C++, once you get the gist of it. You just have to stick with it and keep grinding. You'll get there. Wow, I thought I was the only one using this approach... well, nearly. I don't target Linux 64 and I use MS compilers for Windows (I got burned by MetroWerks C awhile back, and gave up on "alternative" Windows compilers at that point), but otherwise I'm in the same cross-platform C++ heaven you are, I think.
  4. Circular Dependencies

    Agree, parent-child references are a good (and common) way to do this. For your undefined struct problem, you'll need to forward-declare your structs & classes to make the compiler happy: // #include "CMap.h" class CMap; class CCharacter { CMap* m_map; .... }; In this fragment, I comment out the include to the full definition of CMap from my CCharacter.h, because of the circular reference problem you mention. Since the member is a pointer, all the compiler needs to know is that some class called CMap exists. It doesn't need to know its internals since the size of the pointer is the same. You could also use a void*, but this is type-safe. The only downside, is that you can't have any inline methods in CCharacter.h that try to dereference m_map. Hope this helps. *edit* As an aside, the less headers you can avoid #including, the faster your compile time will be.
  5. Is it hard to get hired

    Quote:Original post by VanillaSnake21 I hear that game programming is a very competetive profession and that because a lot of people want to do it its hard to find a job. Is that true. And in general how would I start looking for a job if I've never worked in that field before. Thnx A few years ago, there was a commercial that asked the question, "How do I get a job without experience? How do I get experience without a job?" I think that's what you're asking, at least in the second part of your question. In my experience, there are two answers: - Be lucky enough to find a company that will take a chance on a newbie. Internships can help a lot with this. - Do some game development on your own, outside of class, so that you have something to show an employer that isn't just a class assignment. Either your own game, or help out with someone else's. If all you have to show is classwork then all we really have to look at is your GPA, and that doesn't tell us anything really. It also helps if you get to know a few people in the field you want to be in. Don't underestimate the power of networking! Go to job fairs, trade shows, etc.
  6. Linkage error in Visual C++ 6.0

    Since its C++, another possibility is that the libraries aren't missing. They could be there, but built with a different version of the compiler than what you are using. Linker symbols in MSVC have changed at least once that I'm aware of (it was either from MSVC 5 -> MSVC 6, or MSVC 6 -> MSVC 7, I don't recall, it was awhile ago), and there could have been more changes in later versions. Since you're asking about what libs you're missing, I'm guessing you're using some 3rd party code, maybe from a pre-built binary package. Otherwise, I suggest youl look at what headers you're including (clearly it gets past the complier stage, so you have the headers) and try to deduce what .cpp files might go with them (if its code you wrote) or what library they belong to (if its code from someone else). Hopefully you have some idea what code you're using in your project ! If you have a working .exe that uses your library (maybe a demo that came with it) you can use DUMPBIN to see what its linking to and what symbols its pulling in from each one. You can also try to run cl.exe with the option to save preprocessor output and see if that gives you any clues, in case you have a library that includes a library that includes a library, a few levels deep and you're still getting your bearings. *edit* In other words, there's no good way to figure out where undefined symbols are coming from. You have to have some knowledge about the code you're using and how its structured, at least enough to recognize the symbols and know what they belong to.
  7. C++ Type lookup table

    I *think* what you're trying to do here is equivalent to Java's Class.newInstance(classname) mechanism. That is, given some string (say "VT_STRING"), you want to be able to call CPPTypeLookup::GetCPPType( "VT_STRING" ) and have it return a reference/pointer to a VT_STRING object. The only way I know of to do this, is to use Factory pattern. Have a map between the type ints (or the type strings, take your pick) and a factory object that knows how to produce objects of that type. Something like: class IValueDataFactory { public: IValueData* newInstance(); }; typedef std::map<int,IValueDataFactory*> IValueDataFactoryMap; CPPTypeLookup::GetCPPType( int type ) { // get the map from your type registry IValueDataFactoryMap* map = registry.getTypeFactoryMap(); // FIXME: handle case where type isn't in the map return map[type]->newInstance(); } Does this help any? Or is it the registry mechanism itself you're stuck on? As an aside, I'm assuming you already know about RTTI and operator== (or operator<) overloading and have your own reasons for bypassing them. If not, you might want to read up on them and see if it applies here.
  8. game programming without libraries

    Since you're on Linux anyway, personally, I'd stop at the Framebuffer and ALSA (or OSS, take your pick). You won't be on "bare metal", but you'll be close, and you'll be avoiding all the userspace libraries like X, OpenGL, etc. I think going much lower will get frustrating fast, as the majority of docs you'll find for going directly to the card will be written for x86, not PPC. But that's just me. If after doing Framebuffer and ALSA you still want to go lower, you could always dig into the kernel sources and see what it takes to go directly to the hardware for your architecture.
  9. which 3D API to use?

    There are tons of engines out there. CrystalSpace, OGRE and Irrlicht are just a few. All engines have their pros and cons. afaik, under the covers they all use either OpenGL (if they want to target multiple OS) or DirectX (if they don't) or both. A central concept for both of the 3D API's is the "rendering pipeline". Its much easier to understand/appreciate the engine features if you've spent at least a little time with the API's first. For OpenGL, besides the NeHe tutorials you may also want to get a copy of the red book (I forget the title, but its linked from NeHe's site). If you're already doing 2D you may want to look at ClanLib (clanlib.org). It's a 2D API but it targets both SDL and OpenGL for the backend. Useful if you get into the code and look at how you'd do something with OpenGL vs. how you'd do it with SDL. Eventually you will also want to learn shaders to get the really sexy pixel effects.
  10. Absolutely right that deref'ing this from the initializer is bad. The object is only partially constructed at that point. Should be no problems with using the value of this in the constructor. In this case, though, I don't see any advantage to doing it there vs. the ctor body. I tend not to use this in the init list except when I need to pass it to a ctor of a member field (ex: a logger)... in that case its absolutely necessary to do it that way if you want to avoid two-phase initialization. Given the huge number of #pragma warning( disable : 4355 ) that came up when I used Google to find the specific error text, I'm pretty sure lots of other people will agree with you if you decide its a useless warning and turn it off.
  11. How to build a C language parser

    Not much to add to what others have said here. Compiler construction is a topic unto itself with lots of theory around it. It was a semester unto itself when I was an undergrad. If you're new to this subject, I *highly* recommend you start with ANTLR rather than lexx/yacc (or flex/bison). ANTLR you may be able to pick up just from reading the tutorials, lex/yacc I wouldn't recommend unless you have a copy of the dragon book to go with it. iirc, the ANTLR distro contains grammars for C and Java, and it also has treewalker code.. you may be able to get your "hierarchical data structure" for free if you're happy with the one ANTLR uses. Alternately, you might want to look at a scripting language, such as Lua or Pawn. If you really need the C syntax, SoftIntegration makes a C interpreter (but its expensive), and some of the LPMUDs used C as their extension language. I'm sure there are others.
  12. Intel Compiler help/msdn?

    I believe the Intel compiler is trying to tell you that typecasting this is not needed. Its a no-op. Try removing the (CMyWindow*). Assuming your this pointer derives from CMyWindow and there isn't multiple inheritance going on, you don't need the cast. btw, the operator (CMyWindow*) can generate machine code, same as a reinterpret_cast<>. You're better off with the C++ casts, so you can be more precise about what you are doing. Usually static_cast<> is what you want, or sometimes const_cast<>. I don't even recall the use case for reinterpret_cast<>, I never use it. Incidentally, I think you can use this instead, and dodge the whole issue: SetWindowLong( hWnd, USERDATA, (LONG)this ); As for Intel compiler manuals integration... you'll need to take that up with Intel. ; ) *edit* I just re-read your last post and saw the bit about not being able to type cast this. The short answer is, you're right. With warnings set to max and warnings and errors, I don't think it'll ever let you. Because it isn't safe to do. You may be able to sneak around it with a union though: union { CWindowPtr* ptr; LONG l; } u; u.ptr = this; SetWindowLong(..., u.l, ...);
  13. C++ operator woes

    If it helps, think of a reference as "an implicitly dereferenced pointer". Meaning, it'll take up the storage of a pointer, but you'll use it as though it wasn't (main difference being the use of . to access members instead of * and ->). Its basically syntactic sugar to allow things like operator+= to work for user types the same way they work for builtin types. So to answer your first question, *this is a Vector3D, and conceptually a Vector3D& works also a Vector3D, except that instead of copying the Vector3D and returning it (which is what happens when you leave off &) internally on the stack you just return a pointer. Your friend function doesn't compile for this same reason. new gives you a pointer to a Vector3D but a Vector3D& is acting like the dereferenced object. So the syntax your friend function would be: return *(new Vector3D...). Obviously you don't want that because it'll leak the memory. As for normalize... it has to do with what the compiler is/isnot willing to let you do with the temporary created by operators. STL strings have a similar problem to your vectors. This should work: Vector3D(v1 + v2).Normalize(); Truthfully, if it were me, instead of: Vector3D test = (v1 + v2).Normalize(); I would do this, to get rid of all the temporaries: Vector3D test(v1); test += v2; test.Normalize(); A slightly different idiom, but you get used to it.
  14. switching to 3d game programming on mac?

    catching up? IMO, they were never behind. But with 90+% of the market using Windows, of course you will see more Windows games. That's just economics. But one way to look at it, is if you do make a game for Mac, there's less competition. Just ask Blizzard about that. No idea on Blitz equivalents for Mac. Unity might come close to what you're looking for, but I don't know what language its based on.
  15. Mostly safe. Better to use a size_t instead of an int, since sizeof(void*) > sizeof(int) on some architectures (64-bit systems, for example). Other than that, yes your "trick" of subtracting the address of next from the address of the start of the templated struct is safe. It's actually spec'd that way by ANSI, so its guaranteed to work on any ANSI compliant C compiler: elem->next will always be > elem, struct members are required to be allocated to ascending memory addresses. The "metadata" is padding so that "next" is aligned on a memory address suitable for a pointer. You might need to take that padding into account in your allocator, so that equal structs actually come out equal (vs. being != due to whatever random bits are in the padding). It's a perfectly good solution for cases where it makes sense to compare the raw memory of the struct.