Re: Avoid including header file by declaring class. But what for typedef ???

Discussion in 'C++' started by Jorgen Grahn, Aug 21, 2008.

  1. Jorgen Grahn

    Jorgen Grahn Guest

    On Wed, 20 Aug 2008 12:48:03 -0700 (PDT), <> wrote:
    > On Aug 20, 10:50 pm, nguillot <> wrote:
    >> [snip] I can write
    >> class B;
    >> to avoid including the header file declaring B.

    >
    > You can but you shouldn't, despite lots of generally respected authors
    > recommending it.


    ....

    > Declaring things that the B-developer is quite entitled to change at
    > any time (e.g. from a class to a typedef to a template instantiation)
    > is as bad as the olden-days habit of not using headers, and having
    > extern declarations for the extra-translation-unit functions you plan
    > to call....


    Unlike that old pain, a "class B;" in my code cannot silently cause my
    program to stop working, can it?

    > To make the most of your build tools (e.g. make), you have to work in
    > with their logic about recompilation, not fight it with hacks.


    > Changes with compatible usage should trigger a rebuild.


    I take it that is your main argument against forward declarations.

    I disagree, at least in the case where I am the author of class B and
    can change both B and the code which uses it whenever needed.
    Bringing down compilation times is worth a lot, in my opinion. I also
    prefer my code seeing as few names as possible, even if everything is
    in namespaces and there are no macros with too generic names.

    To answer the original question a bit: I think the problem he sees
    with typedefs is a reason many people prefer not to typedef classes.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
    \X/ snipabacken.se> R'lyeh wgah'nagl fhtagn!
     
    Jorgen Grahn, Aug 21, 2008
    #1
    1. Advertising

  2. Jorgen Grahn

    Guest

    Re: Avoid including header file by declaring class. But what fortypedef ???

    On Aug 22, 1:30 am, Jorgen Grahn <> wrote:
    > Unlike [embedded extern fn declarations], a "class B;" in my code
    > cannot silently cause my program to stop working, can it?


    Depends who you are in the software system, what you call silently and
    working, and what expectations and responsibilities you feel different
    developers involved can have of and to each other.

    As a library developer defining a class X in a header, I would argue
    that you are entitled to replace it with "template <typename T> class
    XT {...}; typedef XT<int> X;", as well-written client code that
    includes your header will seamlessly recompile and work. This is
    standard practice when evolving code is generalised to arbitrary
    types.

    But - silently from the perspective of the library developer who
    doesn't necessarily know about all client usage or trigger client app
    recompilation - poorly-written client code hard-coding "class X;" will
    break. Scenario: Some production issue requires a urgent bug fix and
    instead the app developer finds unrelated parts of their app aren't
    compiling any more and must be fixed simultaneously, delaying
    deployment of the fix. If the library developer considers their
    clients as part of their overall "system" (a responsible attitude and
    generally expected in corporate life at least), then yes their change
    broke their system. But they're not really to blame....

    Can it be worse? Probably. Thinking about all the combinations of
    layers of objects, headers, static vs load-time vs run-time binding
    etc. does my head in and I'd need a better reason for suffering that
    than this thread.

    About the best that can be said is that at least some of these issues
    differ from extern function abuses, where the consequences are more
    consistently in the SIGSEGV category ;-).

    > > To make the most of your build tools (e.g. make), you have to work in
    > > with their logic about recompilation, not fight it with hacks.
    > > Changes with compatible usage should trigger a rebuild.

    >
    > I take it that is your main argument against forward declarations.
    >
    > I disagree, at least in the case where I am the author of class B and
    > can change both B and the code which uses it whenever needed.
    > Bringing down compilation times is worth a lot, in my opinion. I also
    > prefer my code seeing as few names as possible, even if everything is
    > in namespaces and there are no macros with too generic names.


    Forward declaration headers - maintained by the downstream library -
    are the only proper way to handle this. If a header pulls in myriad
    other headers AND has many independent parts then it's a strong
    candidate for separation into multiple headers / forward-declaration
    pairs, with the original header including the parts. This way
    upstream clients can select those parts that are useful without the
    full burden of including extra headers. pImpl / envelope-letter
    idioms help. If managed maturely, the compilation times can almost
    always be kept thoroughly under control and don't begin to justify the
    complications of the "class X;" hack.

    Tony
     
    , Aug 22, 2008
    #2
    1. Advertising

  3. Jorgen Grahn

    Jorgen Grahn Guest

    (A very late response)

    On Fri, 22 Aug 2008 01:57:26 -0700 (PDT), <> wrote:
    > On Aug 22, 1:30 am, Jorgen Grahn <> wrote:
    >> Unlike [embedded extern fn declarations], a "class B;" in my code
    >> cannot silently cause my program to stop working, can it?

    >
    > Depends who you are in the software system, what you call silently and
    > working, and what expectations and responsibilities you feel different
    > developers involved can have of and to each other.
    >
    > As a library developer defining a class X in a header [...]


    You are probably right about the library case, but I do not think it
    is so common that it should dictate general practice.

    My basic assumption was that I was *not* a library developer, i.e.
    that I personally link the final executable, or a close co-worker
    does. Or put more in configuration management terms, that we deliver
    executables, and noone delivers inputs to us, except well-tested and
    stable 3rd-party libraries.

    In that scenario, I can save a lot of work and uncertainty by making
    assumptions about the code (and I can refactor any part of it until
    the assumptions hold).

    And I also believe lots of bad code has been written because it was
    needlessly written as if it was a library. I *still* see classes
    where a lot of work is spent on unused features: "virtual" for classes
    which noone inherits from, copy constructors and operator= for classes
    which noone copies, function arguments with default values which noone
    ever provides ...

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
    \X/ snipabacken.se> R'lyeh wgah'nagl fhtagn!
     
    Jorgen Grahn, Sep 8, 2008
    #3
    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. Newsgroup - Ann
    Replies:
    4
    Views:
    746
    lilburne
    Nov 2, 2003
  2. lutorm
    Replies:
    16
    Views:
    529
    Alf P. Steinbach
    May 23, 2005
  3. free2klim
    Replies:
    2
    Views:
    360
    free2klim
    Jul 21, 2006
  4. Scoots
    Replies:
    10
    Views:
    650
    Scoots
    Jun 19, 2007
  5. oor
    Replies:
    0
    Views:
    1,413
Loading...

Share This Page