Thread: Aggregation (sort of),

  1. #1
    Registered User Terran's Avatar
    Join Date
    May 2008
    Location
    Nashua, NH
    Posts
    100

    Aggregation (sort of),

    I'm sure i'm probably missing the point (arn't i always?), but if i have code;

    Code:
    class Z {
    
         void foo(X x) {};
         void bar(Y y) {};
    };
    class X {
    
          void foo( Y y) {};
          void bar(Z z) {};
    };
    
    class Y {
         
          .....
    
    };
    Even if i just prototype them in the delarations it still won't work right? How do you get around that?
    Sorry, but i'm a Code::Blocks man now.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You get a real design.

    It's hard to tell what foo and bar are supposed to do, but you can always make them free functions (i.e., "normal" functions, functions that don't belong to a particular class), if you don't need private data -- and I'm guessing you don't, because it wouldn't necessarily be available anyway (Z::foo wouldn't be able to access the private data of x, and so on). If you do, you can still make them free functions, but also make them friends.

  3. #3
    Registered User Terran's Avatar
    Join Date
    May 2008
    Location
    Nashua, NH
    Posts
    100
    My question is, since delaration seems to work in a top-down fashion, what happens if i need a use a variable of the second type in the first class decaration, Ad nauseam?
    Sorry, but i'm a Code::Blocks man now.

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You don't. You can use a forward declaration, if you are willing to take a pointer to the data (as mentioned previously); otherwise you make things free functions (as mentioned above); otherwise you think about the problem and your class structure again.

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I agree with tabstop that it really depends on the problem. However, you can try a reference to const, then make a copy inside the function (if you really need a copy). That will allow you to use a forward declaration.

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Isn't it also possible to use forward declarations if objects are passed and returned by value?

    Code:
    class X;
    
    class Y
    {
        X foo(X x);
    };
    
    class X
    {
    };
    
    X Y::foo(X x)
    {
        ...
    }
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    No, it isn't. If it compiles (which it shouldn't, really), then you would get a big, fat warning about how the compiler couldn't call the constructor and destructor.
    It only works for pointers and references (or reliably, that is, since the compiler does not need to call the constructor or destructor).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Does the compiler call constructors or destructors in function prototypes?

    At the point where the function is defined, X will be a complete type. X should also be complete at the points where the function is called. (The class is just a blue-print, it doesn't run any code?)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    When the compiler parses the prototype, X will not be a complete type, so the compiler cannot see the constructor and destructor. Since it's the compiler's job to call the constructor and destructor, it will warn at this point.
    The problem is that your blueprint tells the compiler how to call the code. Let's assume you use the function Y::foo somewhere in your code. At this point, the compiler has no idea what the constructor/destructor is because X is an incomplete type at this point, so it cannot generate correct code for where you use Y::foo.

    On the other hand, if you make it a reference or a pointer, then the compiler does not need to call the constructor or destructor at the point where the function is initiated. Instead, the actual object is created inside the function, your implementation, and at this point, you would have included the correct header so the type X would be complete.

    Let's take an example:
    Code:
    void foo()
    {
        Y y;
        X x = y.foo();
    }
    This should translate to something like:
    Code:
    void foo()
    {
        Y y;
        X local_x;
        X temp_x = y.foo(); // Object returned from y.foo()
        local_x.x(temp_x); // Copy constructor
        temp_x.~x(); // Destructor
    }
    To generate the code, the compiler looks at Y's prototype and sees an incomplete type X and cannot generate correct code.
    If y::foo returns, say, a pointer, then the code becomes:
    Code:
    void foo()
    {
        Y y;
        X* local_x;
        X* temp_x = y.foo(); // Object returned from y.foo()
        local_x.x(temp_x); // Copy constructor
        temp_x.~x(); // Destructor
    }
    Except, the type is no longer x, but x*, which is a variable, not a class, so the compiler can call the constructor and destructor fine.
    Last edited by Elysia; 06-08-2008 at 03:53 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    The larch
    Join Date
    May 2006
    Posts
    3,573
    May-be you are right and there are some hidden traps, but I'm talking about declaring a function that passes and returns incomplete types by value (which compilers accept quite happily), and you are saying that at the point of implementation/definition the type must be complete (which I agree with, of course).

    The difference with pointer/references is that you can implement the function, even if the types are incomplete, if you don't use the arguments for anything that requires the complete type to be known. For example, it seems that you can pass a reference to an incomplete type on to some other function.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You're quite right.
    There is some condition where the compiler may fail to generate correct code if you use forward-declarations with types returning-by-value, but I can't seem to quite pinpoint them. Perhaps some else knows.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    May-be you are right and there are some hidden traps, but I'm talking about declaring a function that passes and returns incomplete types by value (which compilers accept quite happily), and you are saying that at the point of implementation/definition the type must be complete (which I agree with, of course).
    That doesn't fully describe the picture. Beyond declaration and implementation there is also usage. You also can not use any interface utilizing an incomplete type even when you do not directly manipulate the type and the type is complete for implementation of that interface. (Granted, you'd probably only run into this problem with inline forwarding functions.)

    Soma

  13. #13
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    I think the real problem is not the constructor/destructor calls, but the ability to size up a stack frame to pass the object. The prototype represents a calling routine for the function. That calling routine cannot be complete if the size of any parameter or of the return value is not known.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Unfortunately, this does not explain why. You can compile the code if it returns or takes by-value so long as you provide the implementation before the use.
    But the discussion suggested a case where it wasn't possible to reference or define such functions that return by value if the definition isn't available (only a forward declaration supplied).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Straight Insertion Sort function problem
    By StaticKyle in forum C++ Programming
    Replies: 6
    Last Post: 05-12-2008, 04:03 AM
  2. threaded merge sort
    By AusTex in forum Linux Programming
    Replies: 4
    Last Post: 05-04-2005, 04:03 AM
  3. Sorting
    By vasanth in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 11-10-2003, 05:21 PM
  4. radix sort and radix exchange sort.
    By whatman in forum C Programming
    Replies: 1
    Last Post: 07-31-2003, 12:24 PM
  5. Shell Sort vs Heap Sort vs Quick Sort
    By mackol in forum C Programming
    Replies: 6
    Last Post: 11-22-2002, 08:05 PM