Advertisement Jump to content
  • Advertisement

Polymorphic OOP

Member
  • Content Count

    835
  • Joined

  • Last visited

Community Reputation

954 Good

About Polymorphic OOP

  • Rank
    GDNet+
  1. Why has it taken so long for someone to say: B::B(const B &b) : list( b.list ) { }
  2. Polymorphic OOP

    template inheritance?

    Quote:Original post by Fruny template <class T> class A { public: template<class U> A(const A<U>& a, typename enable_if< is_base_of<T,U> >::type* dummy = 0) { // stuff } }; I wouldn't use is_base_of there. is_base_of yields if the left type is a base of the right type, regardless of whether public, private, or protected inheritance were used. As well, if the left type is less qualified than the right, your template would still be instantiated, which again is a mistake. Finally, it will fail to exhibit the desired behavior when T and U are pointers. Really, what you want to do is check whether or not the pointers are convertible. template <class T> class A { public: template<class U> A(const A<U>& a, typename enable_if< is_convertible< U*, T* > >::type* dummy = 0 ) { // stuff } };
  3. Quote:Original post by Emmanuel Deloget BTW the correct way to cast A to B is to call dynamic_cast<>: B *b = dynamic_cast<B*>(a); if (b) // b== NULL -> cast failed { b->value = 5; } You have to activate RTTI if you want this to work. Regards, Actually, you can't dynamic cast there. Dynamic casting requires a polymorphic type, which A is not. Also, dynamic casting isn't even necessarily the prefered way of casting to children either -- you generally only want to dynamic cast if you are uncertain as to whether or not the pointer actually points to a child object (or for cross-casting). If you know that the type actually is of the child type, you may safely use static_cast, or better yet, boost's polymorphic_downcast.
  4. Quote:Original post by soconne Where does the memory allocation for "int value" come from if you're up casting from class A to class B? It's writing to the memory adjacent to where "a" was allocated, which can be anything really (most-likely situation is you could potentially be writing over another dynamically allocated object's memory by accident). This is not a good thing, but it will likely not cause your application to crash (at least not immediately -- it could create many more subtle errors later on in execution).
  5. Polymorphic OOP

    cpy ctr issue

    Quote:Original post by The C modest god I didnt understand where exactly I should put this? template <class T> class DefensePointer { template <class M> friend class DefensePointer; /* ... */ };
  6. Polymorphic OOP

    cpy ctr issue

    Quote:Original post by The C modest god Why do I get this error? can't I access private members of this? You are trying to access private members of the template instantiated with different template arguments (T vs M). When T and M happen to be the same type, you will not get this error, however, if T and M are different, you have to make sure that the instantiations are friends of each other in order to access each others members. (Edit: It's odd that you are getting that exact error as it seems as though it states that M and T are both "Sprite", so that error shouldn't be happening, unless I'm misreading it) Inside the class template's definition, put: template< typename M > friend class DefensePointer; [Edited by - Polymorphic OOP on August 26, 2006 3:26:08 PM]
  7. You either never built Boost or never set up the directories properly. Most libraries in boost are just templates and inline functions that do not require being built before-hand and being linked to. For several libraries, however, this is not the case. Boost.Filesystem and Boost.Regex happen to be two of them. Since you are running VC++8, you can make things easier by avoiding the build process and just downloading the pre-built libraries over at Boost Consulting. More generally, you'd normally have to build and install Boost on your own. This is also necessary if you ever need to build versions grabbed directly from the CVS repository.
  8. Polymorphic OOP

    Why are people using SAFE_DELETE macro

    Quote:Original post by Zahlman P.S. Stroustrup says that implementors are "encouraged" to have pointers get nulled out after deleteing them, but obviously aren't required to. He expressed disappointment that most (almost all?) compiler vendors have chosen not to, if I'm remembering the faq/article/interview/whatever it was correctly. But then, doing such a thing would seem against the C++ "don't pay for what you don't ask for" philosophy. (Maybe if it were only in debug mode?) And anyway, it's silly to expect compiler vendors to do things that aren't mandated ;) I'm pretty sure he said nothing of the sort, but if he did, I have to say that I disagree entirely. For one, it's not just bad because it isn't mandated by the standard, it's bad because it goes against the standard (Edit: after checking the standard, I apologize, as this is not the case, as there is a little note that says the pointer value is indeterminate). What about deleting const pointers? Certainly you wouldn't want the const pointer's value to be changed, or would you? In other words, would you want the pointer to be zeroed-out only if it were non-const, would you want to make it impossible to call delete on a const pointer? If it were the former, then you're just making inconsistent results for an operation that is logically the same. For the latter, all you'd accomplish is making it a hassle to delete the object, since you'd have to just copy the pointer value to a non-const pointer for the sole purpose of deleting the target, in which case you lose all benefits of zeroing out the pointer anyway. This all originates from the fact that a delete operation is an operation on the target of the pointer, not on the pointer itself. What you want to do with the pointer afterwards is entirely up to you and is an entirely unrelated operation and what you want may vary depending on your situation. The "don't pay for what you don't ask for" philosophy, while is generally true, I feel is an extremely minor factor when talking about zeroing after delete.
  9. Polymorphic OOP

    std::vector[vector.size() - 1]

    Quote:Original post by Conner McCloud Quote:Original post by Dave myVector.end() - 1; vector::end() returns an invalid iterator. You can't legally use it to reach a valid one. CM That's not true. It's perfectly fine to go from end to another iterator through iterator operations. This holds for all container types.
  10. Polymorphic OOP

    Pointers Are Weird....

    Quote:Original post by Nypyren In this example, the name "array" by itself is considered to be an address. Not exactly. The name always refers to the entire array, that is to say the type of the expression consisting of the name of the array is the array type itself. In contexts which require a pointer to the element type, a pointer to the first element can be implicitly yielded. Quote:Original post by Nypyren C/C++ let you interchange "int array[###]" and "int *array" almost everywhere. Usually they are not interchangeable, with the only exception I can think of off the top of my head being function parameter lists. Quote:Original post by mnansgar &Board -> Compilation error! (Since declared as an array, we can't take the address of an address!) That's not a compiler error. It's perfectly valid to take the address of an array. The type of such an expression is your_element_type(*)[your_array_size], which is a pointer to an array of a given element type and length. Also note that this is not taking the address of an address. An array is not an address nor is it a pointer.
  11. Polymorphic OOP

    Trouble with template classes (C++)

    As was said, please post the error. One thing I notice is you don't have any const accessors shown. Also: inline typename Matrix4x4<real>::MatrixRow Matrix4x4<real>::operator[]
  12. Polymorphic OOP

    Limiting function template types

    Quote:Original post by Deyja IIRC, boost::is_arithmetic relies on type traits. Which means, to use your template, I have to supply a specialization of is_arithmetic to confirm that yes, my type really is arithmetic, even though it's not built in. His requirements did not mention working for non-built-in types. In it's current form, it will allow the function to be called for all arithmetic types and the template will not be instantiatied for non-arithmetic types. If he actually wanted to allow for other user-defined types, he wouldn't want to use is_arithmetic directly, but rather, he'd want to encapsulate its functionality and allow for specialization (specializing is_arithmetic for non-built-in types is not proper use since the term arithmetic has a fixed meaning in the standard). Quote:Original post by Deyja I say again, don't do this. If it works, let me use it. If not, I'll get a compile error. No problems at all. I have to say, I disagree with you entirely. This is precicely the type of situation that enable_if is great for. It's a simple step towards using Design-by-Contract in C++. If you want to avoid such checks altogether, you may (or may not) still get compiler errors, however they will often be more difficult to comprehend and will occur in unintuitive locations (at the point at which an unsupported functionality is used, rather than at the call-site). Explicit checks catch errors early and can provide much more understandable messages. Quote:Original post by Deyja If I write a class that behaves like a numeric type, and I want to use it with your template, I can't. I'd have to go modify your code to allow it. That is the exact opposite of generic programming. No, you don't have to modify their code to allow it, all you have to do is make your type acknowledge that it supports the desired interface and meets its guarantees. It's not the opposite of generic programming, on the contrary, DBC is extremely powerful in generic programming.
  13. Polymorphic OOP

    Limiting function template types

    Quote:Original post by Kest Is there any way to limit templated function template types? For example, I wrote some math functions which work with generic numerical data. char, short, int, float, double, long, signed, unsigned, etc. They only work for this type of data because some of the functions can return zero, where the return type is of the template type. SFINAE to the rescue. What you want to do is have substituation fail when a certain compile-time condition is not met, in this case you want to check if the type is arithmetic. This is easily done with boost using enable_if and Boost.TypeTraits: #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_arithmetic.hpp> template< typename ParamType > typename ::boost::enable_if< ::boost::is_arithmetic< ParamType > , ParamType > ::type your_function( ParamType arg ) { // Do whatever return arg; }
  14. Quote:Original post by Esmo2000 Embedded classes aren't for external class's use. They are for either, with iterators being the most common example of nested classes used outside of the encapsulated class. As for accessing a declaration of them, you can only do so with the definition of the encapsulating class. If pulling in the encapsulating class's definition seems to be too much, one trick you can use is to just have the desired nested type actually be a non-nested type existing in a detail namespace which is not intended for direct use, and then have a nested typedef in another class (inside class Item in your case) defined to that type. If other parts of the implementation need a declaration of the nested class and you don't want to have to include the definition of the encapsulating class, just use a declaration of the type. Other users of the class don't have to have any knowledge of the fact that the nested type is just a typedef rather than a direct nested class.
  15. Late reply -- I just got back from vacation. Quote:Original post by NotAYakk Quote:Original post by Polymorphic OOP Do NOT do this. Firstly, the virtual inheritance in your example is unecessary (at least in this context it is) and will just bloat the size of your objects and produce longer construction times. It allows the implementation to be inherited from completely seperately, providing a cleaner seperation between interface and implementation. The implementation of your reader and writer can be replaced with an XML reader/writer, and the client could talk to it without giving a care. That has nothing at all to do with virtual inheritance. Again, the virtual inheritance here is entirely unecessary. Quote:Original post by NotAYakk Quote:As well, since you have separate bases, each with their own virtual functions, each one is going to also have its own vtable pointer, once again bloating the object. You should have one vtable per class, not one vtable per instance of the class. I said vtable pointer, not vtable. Each one of your base types needs an entirely separate vtable, and as well, each instance needs a vtable pointer. That means that you have a separate vtable pointer for each base meaning that you need N vtable pointers per instance of the child type, where N is the number of virtual function created in this manner. You may as well have just used a separate function pointer for each function. Quote:Original post by NotAYakk And the objects in question have empty construction. The objects do not have empty construction. Whenever you construct an instance of your type, the vtable pointers and virtual inheritance information need to be initialized. Quote:Original post by NotAYakk Quote:As an example, on my compiler your IOReader type is 48 bytes in size, regardless of the fact that it has no datamembers. If you remove the virtual inheritance, it drops down by half to 24 bytes. If you avoid this method entirely in favor of just putting the virtual functions in the type itself, the size is 4 bytes. On many platforms, 48 bytes of space is, well, ignoreable. It's 48 bytes. Unless you are creating one of these for every pixel on the screen, or are writing code for a gameboy... By 'wasting' 48 bytes, on a system with 1 GB of memory, I've managed to use up 0.0000045% of the system's memory. ;) Having a lot of memory isn't an excuse to blatantly misuse language constructs to make complex and inefficient solutions to problems which have simple and more efficient alternatives.
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!