which of these 3 casts would you prefer?

Discussion in 'C++' started by A, Aug 25, 2011.

  1. A

    A Guest

    int Callback(void *pThis)
    {
    TMyClass *pMC = (TMyClass*)pThis; // C style

    TMyClass *pMC = static_cast<TMyClass*>(pThis); // C++ style but the
    // same as above

    TMyClass *pMC = reinterpret_cast<TMyClass*>(pThis); // Doesn't check if
    // input type was
    // pointer, possibly
    // dangerous
    }

    these 3 do essentially the same. is there any preferred one for void* cast
    like this and why? any difference in speed?
     
    A, Aug 25, 2011
    #1
    1. Advertising

  2. On 8/25/2011 2:58 PM, A wrote:
    > int Callback(void *pThis)
    > {
    > TMyClass *pMC = (TMyClass*)pThis; // C style
    >
    > TMyClass *pMC = static_cast<TMyClass*>(pThis); // C++ style but the
    > // same as above
    >
    > TMyClass *pMC = reinterpret_cast<TMyClass*>(pThis); // Doesn't check if
    > // input type was
    > // pointer, possibly
    > // dangerous
    > }
    >
    > these 3 do essentially the same. is there any preferred one for void* cast
    > like this and why? any difference in speed?


    Casts from `void *` are handled in C++ by `static_cast`. So, that would
    be the one to use in this case. There's no reason to involve a less
    restrictive cast (`reinterpret_cast`) when a more restrictive does the
    job. That's basically the rule I'd follow: in any situation prefer to
    use the most restrictive cast that does the job.

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Aug 26, 2011
    #2
    1. Advertising

  3. On 25.08.2011 23:58, A wrote:
    > int Callback(void *pThis)
    > {
    > TMyClass *pMC = (TMyClass*)pThis; // C style
    >
    > TMyClass *pMC = static_cast<TMyClass*>(pThis); // C++ style but the
    > // same as above
    >
    > TMyClass *pMC = reinterpret_cast<TMyClass*>(pThis); // Doesn't check if
    > // input type was
    > // pointer, possibly
    > // dangerous
    > }
    >
    > these 3 do essentially the same. is there any preferred one for void* cast
    > like this and why? any difference in speed?


    Aim for clarity.

    Cheers & hth.,
     
    Alf P. Steinbach, Aug 26, 2011
    #3
  4. Dnia 25-08-2011 o 23:58:56 A <> napisał(a):

    > int Callback(void *pThis)
    > {
    > TMyClass *pMC = (TMyClass*)pThis; // C style
    >
    > TMyClass *pMC = static_cast<TMyClass*>(pThis); // C++ style but the
    > // same as above
    >
    > TMyClass *pMC = reinterpret_cast<TMyClass*>(pThis); // Doesn't check if
    > // input type was
    > // pointer, possibly
    > // dangerous
    > }
    >
    > these 3 do essentially the same. is there any preferred one for void*
    > cast
    > like this and why? any difference in speed?
    >
    >
    >
    >


    IMHO there is no place for preferences.

    The first is used in c and should be used only in C.
    The second is from C++ and should be used mostly (compiler check if
    conversion is usable)
    The third is a equivalent of the c solution. Compiler checks nothing.

    In c++ should be used only c++ conversion, because mostly compiler (not in
    reinterpret conv.) does some checks of common sense of this conversion.
    And c++ conversion are long and easy to find. The creator of c++ some gave
    arguments: the place of most errors is conversion ;-)

    dynamic_cast is used for child class pointers conversion.
     
    Duga Chernobyl, Aug 26, 2011
    #4
  5. A

    A Guest

    I do not understand though reluctance to use C style casts.

    They can cast to reinterpret_cast but they also try out the weaker cast
    before. It is just automatic way to do what you would do manually - first
    try const_cast, then static_cast and finally reinterpret_cast... yes, it can
    use reinterpret_cast but you would have to use it anyway in a particular
    case where you really need it.

    So what's wrong with little automation, providing that you know what you are
    doing with casts?
     
    A, Aug 26, 2011
    #5
  6. Dnia 26-08-2011 o 14:40:27 A <> napisał(a):

    > I do not understand though reluctance to use C style casts.
    >
    > They can cast to reinterpret_cast but they also try out the weaker cast
    > before. It is just automatic way to do what you would do manually - first
    > try const_cast, then static_cast and finally reinterpret_cast... yes, it
    > can
    > use reinterpret_cast but you would have to use it anyway in a particular
    > case where you really need it.
    >
    > So what's wrong with little automation, providing that you know what you
    > are
    > doing with casts?
    >
    >


    Sometimes you are tired and you don't want to check, if something is good
    or bad. For me compiler is the best friend (in programming ;-)) and always
    set this settings:

    Try search all convertions with c++ style and all with c style. What, do
    you think, is easier to find all of them?

    -Wall -Wextra -pedantic -g -pg

    It is not little automation, but great help ;-)

    if you make a mistake f.e

    if (a = 1) gcc will you ask, if really means it. If you are programmer,
    the common sense makes you to be open for all suggestions of compiler.
    Many people thinks, that computer is evil, but computer makes exactly what
    we said (but not very often what we want ;-))
     
    Duga Chernobyl, Aug 26, 2011
    #6
  7. A

    Edek Guest

    On 08/26/2011 02:40 PM, A wrote:
    > I do not understand though reluctance to use C style casts.
    >
    > They can cast to reinterpret_cast but they also try out the weaker cast
    > before. It is just automatic way to do what you would do manually - first
    > try const_cast, then static_cast and finally reinterpret_cast... yes, it can
    > use reinterpret_cast but you would have to use it anyway in a particular
    > case where you really need it.
    >
    > So what's wrong with little automation, providing that you know what you are
    > doing with casts?
    >
    >


    C++ has many features you do not have to use. If you do not like
    this part of type enforcement, then don't, just mind others working
    on the same code.

    I would prefer static_cast, because
    - it is grepable (C-style cast is not so grepable)
    - it is more strict than reinterpret_cast and C-style.
    If I (or someone else) changes the type of pThis,
    it might rightly generate an error

    In both cases, it might save a lot of time otherwise spent
    on debugging.

    Edek
     
    Edek, Aug 26, 2011
    #7
  8. On Aug 26, 3:05 am, "Duga Chernobyl" <> wrote:
    > Dnia 25-08-2011 o 23:58:56 A <> napisał(a):
    >
    > > int Callback(void *pThis)
    > > {
    > > TMyClass *pMC = (TMyClass*)pThis;                    // C style

    >

    (...)
    > The first is used in c and should be used only in C.


    The cast is not needed in C.

    - Anand
     
    Anand Hariharan, Aug 26, 2011
    #8
  9. A

    Jorgen Grahn Guest

    On Fri, 2011-08-26, Duga Chernobyl wrote:
    > Dnia 26-08-2011 o 14:40:27 A <> napisa??(a):
    >
    >> I do not understand though reluctance to use C style casts.
    >>
    >> They can cast to reinterpret_cast but they also try out the weaker cast
    >> before. It is just automatic way to do what you would do manually - first
    >> try const_cast, then static_cast and finally reinterpret_cast... yes, it
    >> can
    >> use reinterpret_cast but you would have to use it anyway in a particular
    >> case where you really need it.
    >>
    >> So what's wrong with little automation, providing that you know what you
    >> are
    >> doing with casts?


    > Sometimes you are tired and you don't want to check, if something is good
    > or bad. For me compiler is the best friend (in programming ;-))


    Yes, in C++ programming anyway.

    > and always
    > set this settings:
    >
    > Try search all convertions with c++ style and all with c style. What, do
    > you think, is easier to find all of them?
    >
    > -Wall -Wextra -pedantic -g -pg


    I'm surprised you're listing g++ warning options, but omit the topical
    one: "-Wold-style-cast". I use it for all my code.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, Aug 26, 2011
    #9
  10. On 26.08.2011 23:27, Jorgen Grahn wrote:
    >
    > I'm surprised you're listing g++ warning options, but omit the topical
    > one: "-Wold-style-cast". I use it for all my code.


    Thanks for that item.

    Cheers,

    - Alf
     
    Alf P. Steinbach, Aug 27, 2011
    #10
  11. Dnia 26-08-2011 o 23:27:03 Jorgen Grahn <>
    napisał(a):

    > On Fri, 2011-08-26, Duga Chernobyl wrote:
    >> Dnia 26-08-2011 o 14:40:27 A <> napisa??(a):
    >>
    >>> I do not understand though reluctance to use C style casts.
    >>>
    >>> They can cast to reinterpret_cast but they also try out the weaker cast
    >>> before. It is just automatic way to do what you would do manually -
    >>> first
    >>> try const_cast, then static_cast and finally reinterpret_cast... yes,
    >>> it
    >>> can
    >>> use reinterpret_cast but you would have to use it anyway in a
    >>> particular
    >>> case where you really need it.
    >>>
    >>> So what's wrong with little automation, providing that you know what
    >>> you
    >>> are
    >>> doing with casts?

    >
    >> Sometimes you are tired and you don't want to check, if something is
    >> good
    >> or bad. For me compiler is the best friend (in programming ;-))

    >
    > Yes, in C++ programming anyway.
    >
    >> and always
    >> set this settings:
    >>
    >> Try search all convertions with c++ style and all with c style. What,do
    >> you think, is easier to find all of them?
    >>
    >> -Wall -Wextra -pedantic -g -pg

    >
    > I'm surprised you're listing g++ warning options, but omit the topical
    > one: "-Wold-style-cast". I use it for all my code.
    >
    > /Jorgen
    >


    Thanks ;-)
     
    Duga Chernobyl, Aug 27, 2011
    #11
  12. A

    Jorgen Grahn Guest

    On Sat, 2011-08-27, Duga Chernobyl wrote:
    > Dnia 26-08-2011 o 23:27:03 Jorgen Grahn <>
    > napisa??(a):


    >> I'm surprised you're listing g++ warning options, but omit the topical
    >> one: "-Wold-style-cast". I use it for all my code.


    > Thanks ;-)


    You're welcome :) It took me a few years to discover that flag --
    I think programmers in general read their manuals to rarely.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, Aug 27, 2011
    #12
  13. A

    BGB Guest

    On 8/26/2011 5:40 AM, A wrote:
    > I do not understand though reluctance to use C style casts.
    >
    > They can cast to reinterpret_cast but they also try out the weaker cast
    > before. It is just automatic way to do what you would do manually - first
    > try const_cast, then static_cast and finally reinterpret_cast... yes, it can
    > use reinterpret_cast but you would have to use it anyway in a particular
    > case where you really need it.
    >
    > So what's wrong with little automation, providing that you know what you are
    > doing with casts?
    >


    unlike the others here, I don't take much issue with C style casts.


    then again, I am also primarily a C programmer (for various reasons),
    and most of the C++ code I have written has been in a C-like style
    (usually either because for some reason I needed C++, such as
    interfacing with a C++ only library, or because there is C++/CLI but not
    a C/CLI, ...).


    one can also argue that function overloading and operator overloading
    are nifty, but rarely have I found this to be a big issue (one can
    typically sort-of make due with using short macro names to redirect to
    longer operator function names or similar, and with the convention of
    using short suffixes to function names to indicate the argument types or
    similar...).


    it is not that I don't know about OOP or whatever, just that:
    what I usually want done can be done "well enough" in C explicitly using
    structs and vtables (so C can still do OOP, sort of);
    in other cases, I am using a language like C# or Java, or my own
    scripting language (vaguely ActionScript-like);
    it often just so happens to be a bit easier to do multi-direction
    cross-language interfacing in C than in C++.


    not that my case likely represents a normal development process though,
    and if one is doing pure C++ (or pure C++ for application code with C
    mostly in back-end libraries), then the comments made by others here
    make more sense.

    also, FWIW, my own scripting language doesn't have C-like casts (mostly
    for syntactic reasons though, namely syntactic ambiguity), but instead
    splits them into multiple casts indicated by a keyword ("x as type", "x
    as! type", ...).


    or such...
     
    BGB, Aug 27, 2011
    #13
  14. BGB <> wrote:
    > one can also argue that function overloading and operator overloading
    > are nifty, but rarely have I found this to be a big issue (one can
    > typically sort-of make due with using short macro names to redirect to
    > longer operator function names or similar, and with the convention of
    > using short suffixes to function names to indicate the argument types or
    > similar...).


    The reason why function and operator overloading is important is not
    because it's "handy" or "convenient" or anything like that. It's because
    it's *necessary* for generic programming. It's what allows you to do
    things like this:

    template<typename T>
    T foo(T value)
    {
    std::cout << "The input value was " << value << std::endl;
    return std::cos(value);
    }

    The above code would be impossible without function and operator
    overloading. For example in C you have cos(), cosf() and cosl(), and
    you just can't write a macro that would call the proper function based
    on the type of the parameter. In C++ you have just different versions
    of std::cos(), and the proper version will be automatically called
    depending on the type of parameter.

    (You could write *three* macros with different names, but now you have
    not only triplicated your code, you have made it impossible to call
    the macro from other macros without triplicating those too, so the
    triplication becomes contagious. Also, it doesn't allow the user to use
    a custom user-defined type.)

    Likewise it's what allows the std::cout above to work properly.

    This is something the most C programmers don't understand. They are
    not to blame, though, because many C++ programmers don't know this either
    (or have never thought about it).

    > it is not that I don't know about OOP or whatever, just that:
    > what I usually want done can be done "well enough" in C explicitly using
    > structs and vtables (so C can still do OOP, sort of);


    The major problem in C is not the lack of dynamic binding. It's the
    lack of RAII and templates. (And, to some extent, exceptions.)
     
    Juha Nieminen, Aug 27, 2011
    #14
  15. A

    Noah Roberts Guest

    On Aug 26, 5:40 am, "A" <> wrote:
    > I do not understand though reluctance to use C style casts.
    >
    > They can cast to reinterpret_cast but they also try out the weaker cast
    > before. It is just automatic way to do what you would do manually - first
    > try const_cast, then static_cast and finally reinterpret_cast... yes, it can
    > use reinterpret_cast but you would have to use it anyway in a particular
    > case where you really need it.
    >
    > So what's wrong with little automation, providing that you know what you are
    > doing with casts?


    Perhaps a story would help you understand.

    A while back I worked under a guy who used C++ but basically feared
    everything about it. Boy did he love inheritance though. He used
    inheritance as his only method of code reuse. He created these
    gigantic higherarchies that spanned multiple concepts attempting to
    tie them together. Trying to add a new object to this system was a
    nightmare because a lot of the time he put in "assert(false); // this
    function shouldn't be called" as the base object definition instead of
    using pure virtuals. He did this because his higherarchy was a total
    pain in the ass and required you to implement more functions than you
    needed. This of course left one not knowing what functions they
    needed to override until running the program and getting an assert.

    Eventually this guy quit and moved on to other things and places.
    Hopefully he learned something about code design but he was pretty
    stubborn. Once he did, I set about trying to fix the project and put
    it into a state that allowed for more code reuse and in which it was
    easier to add new behavior.

    Did I mention this guy hated everything C++? This included new-style
    casts. He used C casts everywhere. He even used them where they were
    not necessary. For example:

    class Object
    {
    public:
    Object* readObjectA(char* c) { return (Object*)ObjectA(c); }
    ... lots more of these ...
    };

    class ObjectA : public Object { ... };

    Now, I did not realize this was going on at the time. I split all the
    various responsibilities that Object had in its interface into
    multiple base objects and used multiple inheritance to apply those
    interfaces only where they were being used. Sent the code off to
    testing and it starts acting really stupid. What happened?

    Well, the original developer had seen something in the compiler output
    like, "cannot convert ObjectA* to Object*, use a reinterpret or c-
    style cast," and so he did that instead of realizing he needed to put
    these functions in a place that could see the full definition of
    ObjectA so that it COULD do that conversion the way it's supposed to.
    Believing only in all things C this kind of thing comes completely
    natural to him. Of course, a reinterpret cast to one base among many
    is a very bad thing to do.

    This problem was trivial to fix but later I ran into further issues.
    Because there were C style casts all through the code, we had
    opportunity for more issues to come up. This used the Win32 API and
    had a lot of callback functions. These functions would take a type
    number ID (guy hated RTTI and dynamic casting) and then cast to the
    appropriate type, having already casted the long or void* to the base
    type. Often this code would assume it's only going to get a certain
    subset of objects passed to it because they're the only ones that have
    some somewhat related functionality. If the type wasn't of one it
    would assume the other. It would use c-style casts to do so. So the
    code would promptly cast to the wrong derived class object and start
    calling functions on it. This issue did not turn up until I started
    messing with things; it was of course illiciting undefined behavior
    all over the place but nobody was the wiser about it because it just
    worked, and had worked for 15 years.

    Because this guy used c-style casts instead of the appropriate new-
    style (or even the inappropriate one), it was quite impractical to
    hunt down casts like these and fix them. They had to turn up as
    errors, which occasionally they did when we started adding new objects
    to the tree that performed roles that were previously assumed to only
    be performed by a group of classes. We knew that we needed to start
    doing dynamic casts for these and shooting out error or exceptions
    (which the guy also hated of course) instead of allowing undefined
    behavior, but we were stuck because there is no such thing as a
    regular expression that will match c-style casts.

    This product tree had to be scrapped and redone. We were stuck with
    old interfaces, lacked any amount of I18N and were trying to get into
    foreign markets, etc...things that nobody really thought of when the
    project started and because of poor design choices and especially
    because of an abundant use of C-style casts...the amount of work
    necessary to fix the code was astronomical compared to simply redoing
    the whole thing. Cost the company many thousands of dollars to do so
    and they're still at it 3 years later.

    C-style casts are horrible because they can do anything at any time
    without any warning. One minor code change can turn a static cast
    into a reinterpret cast. You can't hunt these things down because
    regular expressions are useless. The undefined behavior they cause
    may or may not turn up at some time in the near future....it may be 2
    decades before your code starts crashing in some place utterly
    unrelated to the cast in an object that has nothing to do with what is
    actually in the memory its using. NOBODY can keep track of every
    place that needs to cast, especially within complex desktop
    applications that use casting quite regularly. Stuff gets lost and
    bad things happen. The new style casts provide a much better method
    because they turn up more errors, you'll get a compiler error instead
    of successful compile when your static_cast is no longer appropriate,
    and can be searched for quite easily. They should be used for all
    cases in which they can be, which is all cases in most projects.
     
    Noah Roberts, Aug 27, 2011
    #15
  16. A

    Noah Roberts Guest

    On Aug 27, 11:38 am, Juha Nieminen <> wrote:
    > BGB <> wrote:
    > > one can also argue that function overloading and operator overloading
    > > are nifty, but rarely have I found this to be a big issue (one can
    > > typically sort-of make due with using short macro names to redirect to
    > > longer operator function names or similar, and with the convention of
    > > using short suffixes to function names to indicate the argument types or
    > > similar...).

    >
    >   The reason why function and operator overloading is important is not
    > because it's "handy" or "convenient" or anything like that. It's because
    > it's *necessary* for generic programming. It's what allows you to do
    > things like this:
    >
    >     template<typename T>
    >     T foo(T value)
    >     {
    >         std::cout << "The input value was " << value << std::endl;
    >         return std::cos(value);
    >     }


    You don't even need to be doing this to run into the lack of function
    overloading as a great annoyance. I recently started working in a
    project where the lead architect insists it's in C (there are a bunch
    of other things that are more frustrating to me about it than that,
    but whatever). I've found the necessity to think of obscure names to
    make sure to avoid any naming conflicts is a serious quandry. For
    example, in writing a generic stack, vector, or managed string class
    (I have no problem with C OOP, it can be elegant in its own way) you
    have many functions that have a related concept but of course are very
    different in implementation. You could use polymorphism to get by,
    but what if you don't want to use polymorphism? You're quite stuck
    having to name functions like isEmpty to things like
    isNamespaceStackEmpty and isNamespaceStringEmpty, and you're always
    going to be worried that somewhere someone else is naming their stack
    or vector functions the same thing.

    Luckily the project code is quite small and this isn't anything but a
    minor annoyance, but I can't imagine having to deal with it on a
    larger scale. In C++ these things just work themselves out and they
    work themselves out quite well in a very direct manner that is easy to
    detect errors. There are rules like ADL and more complex rules when
    possible overloads are templates, but they're actually not that hard
    to remember especially for the gain you get from them. Honestly this
    issue has bugged me more than any lack of operator overloads, etc...
     
    Noah Roberts, Aug 27, 2011
    #16
  17. A

    RaZiel Guest

    On 26.08.2011 23:27, Jorgen Grahn wrote:
    > On Fri, 2011-08-26, Duga Chernobyl wrote:
    >> Dnia 26-08-2011 o 14:40:27 A<> napisa??(a):
    >>
    >>> I do not understand though reluctance to use C style casts.
    >>>
    >>> They can cast to reinterpret_cast but they also try out the weaker cast
    >>> before. It is just automatic way to do what you would do manually - first
    >>> try const_cast, then static_cast and finally reinterpret_cast... yes, it
    >>> can
    >>> use reinterpret_cast but you would have to use it anyway in a particular
    >>> case where you really need it.
    >>>
    >>> So what's wrong with little automation, providing that you know what you
    >>> are
    >>> doing with casts?

    >
    >> Sometimes you are tired and you don't want to check, if something is good
    >> or bad. For me compiler is the best friend (in programming ;-))

    >
    > Yes, in C++ programming anyway.
    >
    >> and always
    >> set this settings:
    >>
    >> Try search all convertions with c++ style and all with c style. What, do
    >> you think, is easier to find all of them?
    >>
    >> -Wall -Wextra -pedantic -g -pg

    >
    > I'm surprised you're listing g++ warning options, but omit the topical
    > one: "-Wold-style-cast". I use it for all my code.



    For those who aren't using GCC, here is an alternative (Perl script):
    http://www.abisource.com/mailinglists/abiword-dev/2003/May/0198.html

    >
    > /Jorgen
    >


    - RaZ
     
    RaZiel, Aug 27, 2011
    #17
  18. A

    BGB Guest

    On 8/27/2011 11:38 AM, Juha Nieminen wrote:
    > BGB<> wrote:
    >> one can also argue that function overloading and operator overloading
    >> are nifty, but rarely have I found this to be a big issue (one can
    >> typically sort-of make due with using short macro names to redirect to
    >> longer operator function names or similar, and with the convention of
    >> using short suffixes to function names to indicate the argument types or
    >> similar...).

    >
    > The reason why function and operator overloading is important is not
    > because it's "handy" or "convenient" or anything like that. It's because
    > it's *necessary* for generic programming. It's what allows you to do
    > things like this:
    >
    > template<typename T>
    > T foo(T value)
    > {
    > std::cout<< "The input value was "<< value<< std::endl;
    > return std::cos(value);
    > }
    >
    > The above code would be impossible without function and operator
    > overloading. For example in C you have cos(), cosf() and cosl(), and
    > you just can't write a macro that would call the proper function based
    > on the type of the parameter. In C++ you have just different versions
    > of std::cos(), and the proper version will be automatically called
    > depending on the type of parameter.
    >
    > (You could write *three* macros with different names, but now you have
    > not only triplicated your code, you have made it impossible to call
    > the macro from other macros without triplicating those too, so the
    > triplication becomes contagious. Also, it doesn't allow the user to use
    > a custom user-defined type.)
    >
    > Likewise it's what allows the std::cout above to work properly.
    >
    > This is something the most C programmers don't understand. They are
    > not to blame, though, because many C++ programmers don't know this either
    > (or have never thought about it).
    >


    yes, fair enough. C does not do this...

    however, it could be argued that *not* having to write duplicated code
    in this case is what is nifty/convinient/...


    as well, there is another partial way around this problem:
    one can implement a dynamic type-system, and then use wrapping and
    run-time type-checking for a lot of this. it is a tradeoff (performance
    is worse, ...), but it works.

    another variant is to use JVM-like "signature strings" which are used
    alongside any data, with a lot of the type-specific behavior being
    handled by character-driven logic.

    both are fairly useful in implementing VMs, and have different merits
    and drawbacks. in my case I end up using both strategies in different
    situations (well, along with having parts of the typesystem being
    essentially driven by queries to a hierarchical database system...).


    otherwise, I had developed a much fancier macro preprocessor that can be
    used with C (using it to implement such combinatorial/"generic" code was
    one thing I had used it for), but I didn't really use it much for a few
    reasons:
    cases where it was needed were fairly rare;
    it is likely that in cases where one feels the need for such a
    mechanism, they are likely "doing it wrong" anyways;
    it is kind of a build hassle to run code though an additional
    preprocessor prior to running it through the main compiler.

    worst case, one will copy/paste the logic a few times and specialize it
    for each type or situation involved (or keep it in memory, and write out
    a specialized version if/when a need for it pops up, so for example
    people have the logic for linked-lists/hashes/quicksort/... generally
    memorized).


    >> it is not that I don't know about OOP or whatever, just that:
    >> what I usually want done can be done "well enough" in C explicitly using
    >> structs and vtables (so C can still do OOP, sort of);

    >
    > The major problem in C is not the lack of dynamic binding. It's the
    > lack of RAII and templates. (And, to some extent, exceptions.)


    RAII normally only really deals with cases which can be dealt with
    manually though (apart from exceptions, which also don't exist in C, and
    things like longjmp are rarely used).

    also, several other major languages, such as Java and C#, also lack RAII
    (with exceptions, this behavior is handled by the use of a "finally"
    clause).
     
    BGB, Aug 27, 2011
    #18
  19. A

    BGB Guest

    On 8/27/2011 12:32 PM, Noah Roberts wrote:
    > On Aug 27, 11:38 am, Juha Nieminen<> wrote:
    >> BGB<> wrote:
    >>> one can also argue that function overloading and operator overloading
    >>> are nifty, but rarely have I found this to be a big issue (one can
    >>> typically sort-of make due with using short macro names to redirect to
    >>> longer operator function names or similar, and with the convention of
    >>> using short suffixes to function names to indicate the argument types or
    >>> similar...).

    >>
    >> The reason why function and operator overloading is important is not
    >> because it's "handy" or "convenient" or anything like that. It's because
    >> it's *necessary* for generic programming. It's what allows you to do
    >> things like this:
    >>
    >> template<typename T>
    >> T foo(T value)
    >> {
    >> std::cout<< "The input value was "<< value<< std::endl;
    >> return std::cos(value);
    >> }

    >
    > You don't even need to be doing this to run into the lack of function
    > overloading as a great annoyance. I recently started working in a
    > project where the lead architect insists it's in C (there are a bunch
    > of other things that are more frustrating to me about it than that,
    > but whatever). I've found the necessity to think of obscure names to
    > make sure to avoid any naming conflicts is a serious quandry. For
    > example, in writing a generic stack, vector, or managed string class
    > (I have no problem with C OOP, it can be elegant in its own way) you
    > have many functions that have a related concept but of course are very
    > different in implementation. You could use polymorphism to get by,
    > but what if you don't want to use polymorphism? You're quite stuck
    > having to name functions like isEmpty to things like
    > isNamespaceStackEmpty and isNamespaceStringEmpty, and you're always
    > going to be worried that somewhere someone else is naming their stack
    > or vector functions the same thing.
    >


    this is a problem of naming conventions...

    for example, a fairly common naming convention is something like:
    library_subsystem_function.

    so, a person would name things more like:
    int MyFooLib_MyContainerStuff_IsHashEmpty()
    {
    ...
    }

    with "MyFooLib" generally being something a bit more accurate.

    now, provided people don't create libraries with the same names, then
    there is not a clash.

    another convention is:
    prefixSomeFunctionName();

    where prefix is the short name of a library.
    however, this needs to be used a little more sparingly, as the chances
    of a 2 to 4 letter prefix or similar clashing are far higher than with a
    longer name.


    > Luckily the project code is quite small and this isn't anything but a
    > minor annoyance, but I can't imagine having to deal with it on a
    > larger scale. In C++ these things just work themselves out and they
    > work themselves out quite well in a very direct manner that is easy to
    > detect errors. There are rules like ADL and more complex rules when
    > possible overloads are templates, but they're actually not that hard
    > to remember especially for the gain you get from them. Honestly this
    > issue has bugged me more than any lack of operator overloads, etc...



    with a good naming convention, then code scales well into the Mloc range
    without too many issues on this front.

    granted, yes, not everyone agrees as to the ideal naming conventions,
    and a lot of older code has had problems here (often due to people not
    properly qualifying names, simply describing the action or type in a
    terse form, and then running into naming conflicts).
     
    BGB, Aug 27, 2011
    #19
  20. A

    Ian Collins Guest

    On 08/28/11 09:37 AM, BGB wrote:
    > On 8/27/2011 11:38 AM, Juha Nieminen wrote:
    >>
    >> The major problem in C is not the lack of dynamic binding. It's the
    >> lack of RAII and templates. (And, to some extent, exceptions.)

    >
    > RAII normally only really deals with cases which can be dealt with
    > manually though (apart from exceptions, which also don't exist in C, and
    > things like longjmp are rarely used).


    The beauty of RAII is you don't have to implement it manually! This
    eliminates a whole class of common programming errors.

    > also, several other major languages, such as Java and C#, also lack RAII
    > (with exceptions, this behavior is handled by the use of a "finally"
    > clause).


    Yet another manual kludge..

    --
    Ian Collins
     
    Ian Collins, Aug 27, 2011
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. clintonG
    Replies:
    17
    Views:
    919
    clintonG
    Oct 13, 2005
  2. Unforgiven
    Replies:
    3
    Views:
    389
    Unforgiven
    Oct 1, 2004
  3. Sathyaish

    What data type would you prefer and why?

    Sathyaish, Sep 2, 2004, in forum: C Programming
    Replies:
    3
    Views:
    381
    CBFalconer
    Sep 2, 2004
  4. Martin B.
    Replies:
    17
    Views:
    1,113
    Öö Tiib
    Sep 10, 2010
  5. Aston J.
    Replies:
    13
    Views:
    665
    Justin Collins
    Mar 16, 2011
Loading...

Share This Page