Cyclic Creation Dependency ?

Discussion in 'C++' started by sakis.panou@btinternet.com, May 16, 2006.

  1. Guest

    Hi all,

    Can anyone explain to me why the copy constructor of the COuterClass is
    getting called for this one? Let me start by saying I reckon this is
    seriously bad way of implementing anything of the sort, we have a way
    around this. I am simply trying to understand the order or creation and
    the reason for the call to the COuterClass copy constructor. Any help
    would be seriously appreciated. Thanks in advance.

    class COuterClass;

    //=============================================================================
    //
    // CInnerClass
    //
    //=============================================================================
    class CInnerClass
    {
    public:
    COuterClass* theOuterClass;

    explicit CInnerClass( COuterClass* pOuterClass ) :
    theOuterClass( pOuterClass )
    {
    cout << "CInnerClass( COuterClass* pOuterClass )" << endl;
    }
    private:
    CInnerClass( ){};
    CInnerClass( const CInnerClass& rhs){};
    const CInnerClass& operator=( const CInnerClass& rhs ) {};
    };

    //=============================================================================
    //
    // COuterClass
    //
    //=============================================================================
    class COuterClass
    {
    public:
    CInnerClass theInnerClass;

    COuterClass( ) :
    theInnerClass( this )
    {
    cout << "COuterClass( )" << endl;
    };

    private:

    COuterClass( const COuterClass& rhs ){};
    const COuterClass& operator=( const COuterClass& rhs ) {};
    };


    int main( ... )
    {
    COuterClass theOuterClass;
    }

    the error I am getting is :

    --------------------Configuration: CyclicDependency - Win32
    Debug--------------------
    Compiling...
    CyclicDependency.cpp
    C:\Temp\CyclicDependency\CyclicDependency.cpp(54) : warning C4355:
    'this' : used in base member initializer list
    C:\Temp\CyclicDependency\CyclicDependency.cpp(61) : error C2248:
    'CInnerClass::CInnerClass' : cannot access private member declared in
    class 'CInnerClass'
    C:\Temp\CyclicDependency\CyclicDependency.cpp(38) : see
    declaration of 'CInnerClass::CInnerClass'
    Error executing cl.exe.

    CyclicDependency.exe - 1 error(s), 1 warning(s)
    , May 16, 2006
    #1
    1. Advertising

  2. * :
    >
    > Can anyone explain to me why the copy constructor of the COuterClass is
    > getting called for this one? Let me start by saying I reckon this is
    > seriously bad way of implementing anything of the sort, we have a way
    > around this. I am simply trying to understand the order or creation and
    > the reason for the call to the COuterClass copy constructor. Any help
    > would be seriously appreciated. Thanks in advance.
    >


    Here you need

    #include <iostream>
    #include <ostream>
    using namespace std;

    but instead of the 'using' directive, do consider using explicit
    qualification like 'std::cout' -- it's a good habit.


    > class COuterClass;
    >
    > //=============================================================================
    > //
    > // CInnerClass
    > //
    > //=============================================================================
    > class CInnerClass
    > {
    > public:
    > COuterClass* theOuterClass;
    >
    > explicit CInnerClass( COuterClass* pOuterClass ) :
    > theOuterClass( pOuterClass )
    > {
    > cout << "CInnerClass( COuterClass* pOuterClass )" << endl;
    > }
    > private:
    > CInnerClass( ){};
    > CInnerClass( const CInnerClass& rhs){};
    > const CInnerClass& operator=( const CInnerClass& rhs ) {};


    Remove the '{}' empty implementations.

    > };
    >
    > //=============================================================================
    > //
    > // COuterClass
    > //
    > //=============================================================================
    > class COuterClass
    > {
    > public:
    > CInnerClass theInnerClass;
    >
    > COuterClass( ) :
    > theInnerClass( this )
    > {
    > cout << "COuterClass( )" << endl;
    > };
    >
    > private:
    >
    > COuterClass( const COuterClass& rhs ){};
    > const COuterClass& operator=( const COuterClass& rhs ) {};


    Remove the '{}' empty implementations.

    The first one is the cause of your compilation error: it uses the
    CInnerClass copy constructor.


    > };
    >
    >
    > int main( ... )


    Your compiler, Microsoft's Visual C++, accepts this non-standard
    signature 'main', as it's allowed to. But it's very bad form. Remove
    the three dots.


    > {
    > COuterClass theOuterClass;
    > }
    >
    > the error I am getting is :
    >
    > --------------------Configuration: CyclicDependency - Win32
    > Debug--------------------
    > Compiling...
    > CyclicDependency.cpp
    > C:\Temp\CyclicDependency\CyclicDependency.cpp(54) : warning C4355:
    > 'this' : used in base member initializer list


    The documentation for you compiler, Microsoft's Visual C++, incorrectly
    states that "The this pointer is valid only within nonstatic member
    functions. It cannot be used in the initializer list for a base class.".

    That's rubbish.

    Turn off the silly-warning by using that compiler's #pragma mechanism
    (it's a very good compiler when you configure it to be
    standard-conforming, but it's one of the very worst out of the box).


    I've set follow-ups to [comp.os.ms-windows.programmer.win32].

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, May 16, 2006
    #2
    1. Advertising

  3. <> wrote in message
    news:...
    : Hi all,
    :
    : Can anyone explain to me why the copy constructor of the COuterClass is
    : getting called for this one? Let me start by saying I reckon this is
    : seriously bad way of implementing anything of the sort, we have a way
    : around this. I am simply trying to understand the order or creation and
    : the reason for the call to the COuterClass copy constructor. Any help
    : would be seriously appreciated. Thanks in advance.
    :
    : class COuterClass;
    :
    :
    //=============================================================================
    : //
    : // CInnerClass
    : //
    :
    //=============================================================================
    : class CInnerClass
    : {
    : public:
    : COuterClass* theOuterClass;
    :
    : explicit CInnerClass( COuterClass* pOuterClass ) :
    : theOuterClass( pOuterClass )
    : {
    : cout << "CInnerClass( COuterClass* pOuterClass )" << endl;
    : }
    : private:
    : CInnerClass( ){};
    : CInnerClass( const CInnerClass& rhs){};
    : const CInnerClass& operator=( const CInnerClass& rhs ) {};
    : };
    :
    :
    //=============================================================================
    : //
    : // COuterClass
    : //
    :
    //=============================================================================
    : class COuterClass
    : {
    : public:
    : CInnerClass theInnerClass;
    :
    : COuterClass( ) :
    : theInnerClass( this )
    : {
    : cout << "COuterClass( )" << endl;
    : };
    :
    : private:
    :

    The error is reported for this line: [ you should have indicated
    this in your post ]
    : COuterClass( const COuterClass& rhs ){};


    The copy constuctor does not specify how to construct/initialize
    member theInnerClass. Therefore its default constructor has
    to be called -- but it is inaccessible (private to theInnerClass).

    Has nothing to do with a cyclic dependency...



    --
    http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
    Brainbench MVP for C++ <> http://www.brainbench.com
    Ivan Vecerina, May 16, 2006
    #3
  4. red floyd Guest

    wrote:
    > Hi all,
    >
    > Can anyone explain to me why the copy constructor of the COuterClass is
    > getting called for this one? Let me start by saying I reckon this is
    > seriously bad way of implementing anything of the sort, we have a way
    > around this. I am simply trying to understand the order or creation and
    > the reason for the call to the COuterClass copy constructor. Any help
    > would be seriously appreciated. Thanks in advance.
    >


    You're not calling the COuterClass copy constructor, you're assigning
    the *POINTER* to an outerclass that was passed in as a parameter to the
    constrcutor to the "theOuterClass" member.

    > class COuterClass;
    >
    > //=============================================================================
    > //
    > // CInnerClass
    > //
    > //=============================================================================
    > class CInnerClass
    > {
    > public:
    > COuterClass* theOuterClass;
    >
    > explicit CInnerClass( COuterClass* pOuterClass ) :
    > theOuterClass( pOuterClass )
    > {
    > cout << "CInnerClass( COuterClass* pOuterClass )" << endl;
    > }
    > private:
    > CInnerClass( ){};
    > CInnerClass( const CInnerClass& rhs){};
    > const CInnerClass& operator=( const CInnerClass& rhs ) {};
    > };
    >
    > //=============================================================================
    > //
    > // COuterClass
    > //
    > //=============================================================================
    > class COuterClass
    > {
    > public:
    > CInnerClass theInnerClass;


    This declaration should blow up. CInnerClass has a private constructor
    and COuterClass is not a friend.

    > COuterClass( ) :
    > theInnerClass( this )
    > {
    > cout << "COuterClass( )" << endl;
    > };
    >
    > private:
    >
    > COuterClass( const COuterClass& rhs ){};
    > const COuterClass& operator=( const COuterClass& rhs ) {};
    > };
    >
    >
    > int main( ... )
    > {
    > COuterClass theOuterClass;
    > }
    >
    > the error I am getting is :
    >
    > --------------------Configuration: CyclicDependency - Win32
    > Debug--------------------
    > Compiling...
    > CyclicDependency.cpp
    > C:\Temp\CyclicDependency\CyclicDependency.cpp(54) : warning C4355:
    > 'this' : used in base member initializer list
    > C:\Temp\CyclicDependency\CyclicDependency.cpp(61) : error C2248:
    > 'CInnerClass::CInnerClass' : cannot access private member declared in
    > class 'CInnerClass'
    > C:\Temp\CyclicDependency\CyclicDependency.cpp(38) : see
    > declaration of 'CInnerClass::CInnerClass'
    > Error executing cl.exe.
    >
    > CyclicDependency.exe - 1 error(s), 1 warning(s)
    >


    The warning about "this" on line 54 is safely ignorable. It's letting
    you know that your object may not be fully constructed, so whatever
    you're passing "this" to needs to be careful.
    red floyd, May 16, 2006
    #4
  5. Sakis Guest

    Hi all,

    First of all I would like to thank once more everyone for taking the
    time to read this message and to reply to it.

    The problem with the original code posted here is in the area of the
    copy constructor for the COuterClass in that we didn't include the full
    intended initialisation list.

    When the compiler was attempting to build the code for the copy
    constructor of the COuterClass - althought not called - it was
    obviously trying to use the default constructor of the CInnerClass due
    to the CInnerClass theInnerClass property. By changing the copy
    constructor to:

    COuterClass( const COuterClass& rhs ) :
    theInnerClass( this )
    {
    cout << "COuterClass( const COuterClass& rhs )" << endl;
    };

    We explicitly forcing the compiler to use the explicit provide
    constructor of the CInnerClass.

    Here is the modified code, that works as originally intenteded.

    class COuterClass;

    //=============================================================================
    //
    // CInnerClass
    //
    //=============================================================================
    class CInnerClass
    {
    public:

    explicit CInnerClass( COuterClass* pOuterClass ) :
    theOuterClass( pOuterClass )
    {
    cout << "CInnerClass( COuterClass* pOuterClass )" << endl;
    }


    private:

    COuterClass* theOuterClass;

    CInnerClass( ){};
    CInnerClass( const CInnerClass& rhs){};
    const CInnerClass& operator=( const CInnerClass& rhs ) {};
    };

    //=============================================================================
    //
    // COuterClass
    //
    //=============================================================================
    class COuterClass
    {
    public:


    COuterClass( ):
    theInnerClass( this )
    {
    cout << "COuterClass( )" << endl;
    };

    CInnerClass theInnerClass;

    private:

    COuterClass( const COuterClass& rhs ) :
    theInnerClass( this )
    {
    cout << "COuterClass( const COuterClass& rhs )" << endl;
    };

    const COuterClass& operator=( const COuterClass& rhs ) {};
    };
    Sakis, May 17, 2006
    #5
    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. Dennis Lerche

    Cyclic Dependency problem

    Dennis Lerche, May 11, 2004, in forum: C++
    Replies:
    6
    Views:
    11,185
    Khaled.Jouda
    Jul 5, 2010
  2. Nick Forrington

    Cyclic dependency

    Nick Forrington, Nov 16, 2004, in forum: C++
    Replies:
    6
    Views:
    436
    Nick Forrington
    Nov 17, 2004
  3. Replies:
    3
    Views:
    614
    Michael Mair
    Apr 22, 2006
  4. pallav

    Cyclic header dependency

    pallav, Apr 12, 2007, in forum: C++
    Replies:
    1
    Views:
    489
  5. pallav

    Cyclic header dependency

    pallav, Apr 12, 2007, in forum: C++
    Replies:
    3
    Views:
    376
    Michael
    Apr 13, 2007
Loading...

Share This Page