Cyclic Creation Dependency ?

S

sakis.panou

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)
 
A

Alf P. Steinbach

* (e-mail address removed):
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].
 
I

Ivan Vecerina

: 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...
 
R

red floyd

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.
 
S

Sakis

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 ) {};
};
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top