C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Forwarding problem: 2 Classes have methods with instanze of
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Rolf Hemmerling
Guest





PostPosted: Fri Apr 09, 2004 1:32 pm    Post subject: Forwarding problem: 2 Classes have methods with instanze of Reply with quote



Hello !

Newbie question:
Forwarding problem with C++ ( I never learned about such problem with
Java ! Am I right, is it a C++ only (and so NON-Java, NON-Smalltalk
problem, and how to solve it ?):

Description of the forwarding problem:

2 Classes have methods with instanze of the other class as parameter !
Yes, I have a useful application for that, indeed I learned it with
Smalltalk and Java as to be of "good OO design style", to separate data
from UI ect.

With MinGW = GnuC++, there is the error message
"c.h:5: `B' was not declared in this scope"

it did NOT help to put any "forwarding class declarations" like

class B;
class C;

in the head of the files :-(

This is a reduced, non-runnable example where it happens:

#### C.h ###########
#ifndef C_H
#define C_H
#include "b.h"
class C { public:
void execute(B parameter);
};
#endif

#### main.cpp ###########
#include "b.h"
#include "c.h"
void C::execute(B parameter){}}
int main(int argc, char *argv[])
{ return 0; }

#### b.h ###########
#ifndef B_H
#define B_H
#include "c.h"
class B {
public:
void execute(C parameter);
};
#endif

#### b.cpp ###########
#include "b.h"
#include "c.h"
void B::execute(C parameter){}

###############

Any workaround ?

Sincerely
Rolf
--
/ / / Alone on the data highway...
/ / like on an allee in Hannover-Herrenhausen
/ / / The Hemmerling (R) WEB site - Rolf Hemmerling,Germany
/ / / http://www.hemmerling.com/


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Arne Adams
Guest





PostPosted: Sat Apr 10, 2004 11:14 am    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote



Hi Rolf,
forward declaring a class helps if the compiler does not need to see the
definition of that class. This is not true if you declare a function that
has that class as a parameter (per copy) or return (per copy).

You should change the signature of your Execute functions to either:
- void execute(B&) // if execute needs a valid B-Object and
needs to invoke nonconst memberfunctions on that object or manipulate the
state of that object directly

- void execute(const B&) // if execute needs a valid B-Object and does
not need to invoke nonconst memberfunctions on that object nor manipulate
the state of that object directly

- void execute(B*) // if execute does not need a valid
B-Object and may invoke nonconst memberfunctions on that object or
manipulate the state of that object directly

- void execute(const B*) // if execute does not need a valid B-Object
and does not need to invoke nonconst memberfunctions on that object nor
manipulate the state of that object directly

The same for those functions that use a forward declared C object per copy.

HTH

Arne

"Rolf Hemmerling" <hemmerling (AT) gmx (DOT) net> schrieb im Newsbeitrag
news:c55m74$2p2jvf$1 (AT) ID-38883 (DOT) news.uni-berlin.de...
Quote:
Hello !

Newbie question:
Forwarding problem with C++ ( I never learned about such problem with
Java ! Am I right, is it a C++ only (and so NON-Java, NON-Smalltalk
problem, and how to solve it ?):

Description of the forwarding problem:

2 Classes have methods with instanze of the other class as parameter !
Yes, I have a useful application for that, indeed I learned it with
Smalltalk and Java as to be of "good OO design style", to separate data
from UI ect.

With MinGW = GnuC++, there is the error message
"c.h:5: `B' was not declared in this scope"

it did NOT help to put any "forwarding class declarations" like

class B;
class C;

in the head of the files :-(

This is a reduced, non-runnable example where it happens:

#### C.h ###########
#ifndef C_H
#define C_H
#include "b.h"
class C { public:
void execute(B parameter);
};
#endif

#### main.cpp ###########
#include "b.h"
#include "c.h"
void C::execute(B parameter){}}
int main(int argc, char *argv[])
{ return 0; }

#### b.h ###########
#ifndef B_H
#define B_H
#include "c.h"
class B {
public:
void execute(C parameter);
};
#endif

#### b.cpp ###########
#include "b.h"
#include "c.h"
void B::execute(C parameter){}

###############




[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Stephen Ludin
Guest





PostPosted: Sat Apr 10, 2004 11:18 am    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote



Rolf Hemmerling wrote:

Quote:
Hello !

Newbie question:
Forwarding problem with C++ ( I never learned about such problem
with Java ! Am I right, is it a C++ only (and so NON-Java,
NON-Smalltalk problem, and how to solve it ?):

Description of the forwarding problem:

2 Classes have methods with instanze of the other class as parameter
! Yes, I have a useful application for that, indeed I learned it
with Smalltalk and Java as to be of "good OO design style", to
separate data from UI ect.

With MinGW = GnuC++, there is the error message
"c.h:5: `B' was not declared in this scope"

it did NOT help to put any "forwarding class declarations" like

class B;
class C;

in the head of the files :-(

This is a reduced, non-runnable example where it happens:

#### C.h ###########
#ifndef C_H
#define C_H
#include "b.h"
class C { public:
void execute(B parameter);
};
#endif

#### main.cpp ###########
#include "b.h"
#include "c.h"
void C::execute(B parameter){}}
int main(int argc, char *argv[])
{ return 0; }

#### b.h ###########
#ifndef B_H
#define B_H
#include "c.h"
class B {
public:
void execute(C parameter);
};
#endif

#### b.cpp ###########
#include "b.h"
#include "c.h"
void B::execute(C parameter){}

###############

Any workaround ?

Sincerely
Rolf


Rather than passing the parameters by value, which requires the
compiler to see the declaration of the class, pass by const reference
which simply requires a forard declaration:

(header guards removed for clarity)

#### c.h ###########
class B;

class C {
public:
void execute( const B ¶meter );
};
#endif

#### c.cpp ###########
#include "c.h"
#include "b.h"

void C::execute( const B ¶meter ) { }

#### b.h ###########

class C;

class B {
public:
void execute( const C ¶meter );
};

#### b.cpp ###########
#include "b.h"
#include "c.h"

void B::execute( const C ¶meter ) { }

For reference, this subject get exhaustive treatment in:
More Effective C++ (Meyers)
Large Scale C++ Software Design (Lakos)
Exceptional C++ (Sutter)

-stephen

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ali Cehreli
Guest





PostPosted: Sat Apr 10, 2004 11:23 am    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote

Rolf Hemmerling <hemmerling (AT) gmx (DOT) net> wrote

Quote:
Hello !

Newbie question:
Forwarding problem with C++ ( I never learned about such problem with
Java ! Am I right, is it a C++ only (and so NON-Java, NON-Smalltalk
problem, and how to solve it ?):

Description of the forwarding problem:

2 Classes have methods with instanze of the other class as parameter !
Yes, I have a useful application for that, indeed I learned it with
Smalltalk and Java as to be of "good OO design style", to separate data
from UI ect.

With MinGW = GnuC++, there is the error message
"c.h:5: `B' was not declared in this scope"

it did NOT help to put any "forwarding class declarations" like

class B;
class C;

in the head of the files Sad

If you also removed the unnecessary #include statements after doing
that, that would work.

Quote:

This is a reduced, non-runnable example where it happens:

#### C.h ###########
#ifndef C_H
#define C_H
#include "b.h"
class C { public:
void execute(B parameter);
};
#endif

#### main.cpp ###########
#include "b.h"
#include "c.h"
void C::execute(B parameter){}}
int main(int argc, char *argv[])
{ return 0; }

#### b.h ###########
#ifndef B_H
#define B_H
#include "c.h"
class B {
public:
void execute(C parameter);
};
#endif

#### b.cpp ###########
#include "b.h"
#include "c.h"
void B::execute(C parameter){}

###############

The output from g++ 3.2 when compiling b.cpp is helpful:

In file included from b.h:3,
from b.cpp:1:
c.h:5: `B' was not declared in this scope
c.h:5: parse error before `)' token
In file included from b.h:3,
from main.cpp:1:

The preprocessor output shows why:

# 1 "b.cpp"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "b.cpp"
# 1 "b.h" 1


# 1 "c.h" 1


# 1 "b.h" 1
# 4 "c.h" 2
class C { public:
void execute(B parameter);
};
# 4 "b.h" 2
class B {
public:
void execute(C parameter);
};
# 2 "b.cpp" 2

void B::execute(C parameter){}


Quote:

Any workaround ?

Sincerely
Rolf

The way to fix your problem with minimum changes is to use forward
declarations and to remove the unnecessary #includes:

// c.h
#ifndef C_H
#define C_H

class B;

class C { public:
void execute(B parameter);
};
#endif

// b.h
#ifndef B_H
#define B_H

class C;

class B {
public:
void execute(C parameter);
};
#endif

c.h doesn't need to know about B's definition, and b.h doesn't need to
know about C's definition. Those definitions are needed in main.cpp
only.

In general, when two classes need to contain each other, then at least
one of them must contain the other by reference (pointer). In this
case, C contains B by reference:

// c.h
#ifndef C_H
#define C_H

class B;

class C {
B * b_;

public:
void execute(B parameter);
};
#endif

// b.h
#ifndef B_H
#define B_H
#include "c.h"

class B {

C c;

public:
void execute(C parameter);
};
#endif

In production code, a plain pointer member like C::b_ may be a source
of trouble. As written, it seems like b_ is owned by some other
object.

If the owner is actually C, then the lifetime of C::b_ better be
handled in another way. One way might be to use a smart pointer:

boost::shared_ptr<B> b_;

Ali

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Y. Alp Özmert
Guest





PostPosted: Sat Apr 10, 2004 11:25 am    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote

Rolf Hemmerling wrote:

[...]
it did NOT help to put any "forwarding class declarations" [...]
in the head of the files Sad
[...]

Hi,

it alone wouldn't help, if the two headers continue to include the other
one, causing an infinite recursion Smile We even don't need to substitue
the #include with a forward declaration in both of them, just one would
suffice.

Quote:
#### C.h ###########
#ifndef C_H
#define C_H
_class B;_
class C { public:
void execute(B parameter);
};
#endif

#### b.h ###########
#ifndef B_H
#define B_H
_class C;_
class B {
public:
void execute(C parameter);
};
#endif

#### main.cpp ###########
#include "b.h"
#include "c.h"
void C::execute(B parameter){}}
int main(int argc, char *argv[])
{ return 0; }


#### b.cpp ###########
#include "b.h"
#include "c.h"
void B::execute(C parameter) {}

###############



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
David Olsen
Guest





PostPosted: Sat Apr 10, 2004 11:25 am    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote

Rolf Hemmerling wrote:
Quote:
2 Classes have methods with instanze of the other class as parameter !
Yes, I have a useful application for that, indeed I learned it with
Smalltalk and Java as to be of "good OO design style", to separate data
from UI ect.

With MinGW = GnuC++, there is the error message
"c.h:5: `B' was not declared in this scope"

it did NOT help to put any "forwarding class declarations" like
class B;
class C;
in the head of the files :-(

This is a reduced, non-runnable example where it happens:

You have to put the forward declarations in exactly the right places.
Here is code that does compile:

==== b.h ====
#ifndef B_H
#define B_H
class C;
class B {
public:
void execute(C parameter);
void test() { }
};
#endif

==== b.cpp ====
#include "b.h"
#include "c.h"
void B::execute(C parameter) {
parameter.test();
}

==== c.h ====
#ifndef C_H
#define C_H
class B;
class C {
public:
void execute(B parameter);
void test() { }
};
#endif

==== c.cpp ====
#include "c.h"
#include "b.h"
void C::execute(B parameter) {
parameter.test();
}


--
David Olsen
[email]qg4h9ykc5m (AT) yahoo (DOT) com[/email]


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
White Wolf
Guest





PostPosted: Sat Apr 10, 2004 12:10 pm    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote

Rolf Hemmerling wrote:
Quote:
With MinGW = GnuC++, there is the error message
"c.h:5: `B' was not declared in this scope"

it did NOT help to put any "forwarding class declarations" like

class B;
class C;

in the head of the files Sad

Indeed! I have added some "comments" for you to see what is happening, they
use a non-standard extension to the preprocessor, the #warning:

8<---main.cpp
#warning "main.cpp reading b.h"
#include "b.h"
#warning "main.cpp reading c.h"
#include "c.h"

void C::execute(B parameter){}}
void B::execute(C parameter){}}

int main() { }
--->8

I have also dropped the b.cpp for now, just placed the B::execute into
main.cpp.

8<---b.h
#warning "READING b.h!"
#ifndef B_H
#define B_H
#include "c.h"
class B {
public:
void execute(C parameter);
};
#endif
--->8

8<---c.h
#warning "READING c.h!"
#ifndef C_H
#define C_H
#include "b.h"
class C { public:
void execute(B parameter);
};
#endif
--->8


So let's see, what the compiler says. I have trimmed it down a bit:

8<--- Compiler diagnostics trimmed:
Compiling source file(s)...
main.cpp
main.cpp:1:2: warning: #warning "main.cpp reading b.h"
In file included from main.cpp:2:
b.h:1:2: warning: #warning "READING b.h!"
In file included from b.h:4,
c.h:1:2: warning: #warning "READING c.h!"
In file included from c.h:4,
b.h:1:2: warning: #warning "READING b.h!"
In file included from b.h:4,
from main.cpp:2:
c.h:6: error: `B' was not declared in this scope
--->8

So what does this say?

- main.cpp includes b.h
- b.h includes c.h, *before* it declares the class B!
- c.h includes b.h...

But the header guard PREVENTS b.h from being compiled again! So it does not
matter if you put any class A and class B in there, it would not compile
anyway...

What I suspect is that there are actually two problems with this code. One
is that is does not compile. We can make it to compile, but then there will
be another thing I do not like, still in it. Smile First let's see the first
thing. (I read Alice in Wonderland Smile )

What (order) you need to achieve to compile your code with the classes
passed by value is this:

class C;

class B {public: int exec(C par); }

class C {public: int exec(B par); }

int C::exec(B par) {}

int B::exec(C par) {}

or the other way around, with class B being "forward declared" etc.

One way to do this is:

8<---b.h
#warning "READING b.h!"
#ifndef B_H
#define B_H
#include "c.h"
class B {
public:
void execute(C parameter);
};
#endif
--->8

8<---c.h
#ifndef C_H
#define C_H
// I need a class B to exist:
class B;
class C { public:
inline void execute(B parameter);
};
// Now I will need it fully declared:
#include "b.h"
void C::execute(B parameter){}}
#endif
--->8

And the same trick in B. With this version you can have inline functions.
In more simple version you will not include b.h into c.h and c.h into b.h,
but you will have a c.cpp including b.h and having the definition of
B::execute in it and the same for class C.

So, we have got the thing sorted out. What is still wrong? Both execute
functions take a *copy* of their arguments! That is usually not what you
want to do. You have to remember that in C++ (unlike Java) you do not work
with references or handles of types if you write class C! If I know it
correctly, in Java asking for varname with the class type C is - in
reality - a handle to a class type C or anything which inherits from or
implements C (if it is an interface). In C++ if I write class C varname I
get the whole thing there. Hm. Not really a perfect wording, so I escape
to "pictures". If you can, change your reader to use non-proportional fonts
(like the Courier family).

Let's assume C has two integers inside called i and j.

Java:

class C c = new C; // If you have that syntax

+-+
+-+ |i|
Quote:
c|-----..--->|-|
+-+ |j|

+-+

So you will have something, which *refers* to the real object, which can be
anywhere in the memory, it can even be moved around by the garbage
collector!

In C++ hoever you get the whole thing right there, where you declare it:

The line below does exactly the same as the Java equivalent, I mean it
creates a default-constructed class of type C. No new needed.

class C c;

+-+
Quote:
i|
-|
j|
+-+


This is the variable named c above. You can see that I had no place to
write the name c anywhere, because variable c in itself is the two integers:
i and j.

Now this means, that when you pass a class by value to a function, you will
copy it:

// struct is same as class but I
// do not need to write public
struct A {
int i,j;
};

void f( A a) {
a.i=42;
a.j=7;
};

#include <iostream>

using std::cout;
using std::endl;

int main() {
A ma = {1,2};
f(ma);
cout << ma.i << "," << ma.j << endl;
}

This will print:
1,2
because f has modified a *copy* of the object.

That is the reason why we usually use so-called references when we pass
arguments to functions where they have to get modified. Change the
signature of f() to:
void f( A &a) {

In this case the call f(ma) will /bind/ the reference called a to the
variable called ma, and inside the function it will get modified. The
program will print 42,7.

Even in cases when we do not want to modify the class we pass them as
references, but as const references. Like f(A const &); which will prevent
f() from modifying A. So why don't we just take a copy? For many reasons.
First of all copying of an object is almost always more expensive than
binding a reference to it. Binding a reference is about the cost of copying
an integer, while most class types will be larger than that. Another thing
is that passing a class by value (as a copy) reuqires that the class _can_
in fact be copied. And some classes we make just do not like the idea of
being copied, so they disable copying:

// a class, which cannot be duplicated:
class no_copy {
public:
no_copy() {}
private:
no_copy(no_copy&other);
no_copy const &operator=(no_copy&other);
};

The above class has its copy-constructor (observe that it takes (has to
take) its argument (the thing to be copied) by reference) and copy
assignment operators in the private part of the class. So they cannot be
accessed from the outside, for example by a function. And it is probably
not clear from the above example, but they are usually not implemented
either. They only have declarations, but no definition anywhere.

I hope that my post is understandable. I am writing it at 4am, so I am not
100% sure. :-)

--
WW aka Attila
:::
A company is known by the people it keeps.



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Stefan Slapeta
Guest





PostPosted: Sat Apr 10, 2004 12:23 pm    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote

Rolf Hemmerling wrote:

Quote:
Hello !

Newbie question:
Forwarding problem with C++ ( I never learned about such problem with
Java ! Am I right, is it a C++ only (and so NON-Java, NON-Smalltalk
problem, and how to solve it ?):

First of all, I think what you stated below is not what is commonly
known as 'forwarding problem'. What you mean is a common problem with
forward declarations.

Quote:
Description of the forwarding problem:

2 Classes have methods with instanze of the other class as parameter !
Yes, I have a useful application for that, indeed I learned it with
Smalltalk and Java as to be of "good OO design style", to separate data
from UI ect.


Nope, sorry! - 2 Classes which instatiate each other is never a good
idea. I.e. this is what we call a 'cyclic dependency' and a very bad
design flaw in OO (not just in C++) and should be avoided under any
circumstances. (When you are more familiar with C++, I can recommend
reading John Lakos, 'Large Scale C++ Software Design'.)


Quote:
With MinGW = GnuC++, there is the error message
"c.h:5: `B' was not declared in this scope"

it did NOT help to put any "forwarding class declarations" like


Concerning your problem: if you want to pass objects (and not classes,
because classes are just definitions) by value like you did, you can't
just declare a forward reference like 'class A;' because the compiler
does not know the size of the object it should pass in this case.

However, you never should pass objects by value, except there is a very
special reason for doing so!

Try to pass it per 'const B&', then you can also use forward references
to satisfy the compiler!


S.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
John Potter
Guest





PostPosted: Sat Apr 10, 2004 12:26 pm    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote

On 9 Apr 2004 09:32:34 -0400, Rolf Hemmerling <hemmerling (AT) gmx (DOT) net>
wrote:

Quote:
it did NOT help to put any "forwarding class declarations" like

class B;
class C;

in the head of the files Sad

It will when done right.

Quote:
This is a reduced, non-runnable example where it happens:

#### C.h ###########
#ifndef C_H
#define C_H
#include "b.h"

Do not include b.h.

class B;

Quote:
class C { public:
void execute(B parameter);
};
#endif

#### main.cpp ###########
#include "b.h"
#include "c.h"
void C::execute(B parameter){}}

This belongs in c.cpp

Quote:
int main(int argc, char *argv[])
{ return 0; }

#### b.h ###########
#ifndef B_H
#define B_H
#include "c.h"

Do not include c.h

class C;

Quote:
class B {
public:
void execute(C parameter);
};
#endif

#### b.cpp ###########
#include "b.h"
#include "c.h"
void B::execute(C parameter){}

Now create c.cpp just like this one.

John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Phil
Guest





PostPosted: Sat Apr 10, 2004 1:56 pm    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote

Rolf Hemmerling wrote:

Quote:
Hello !

Newbie question:
Forwarding problem with C++ ( I never learned about such problem with
Java ! Am I right, is it a C++ only (and so NON-Java, NON-Smalltalk
problem, and how to solve it ?):
....
Any workaround ?

Sincerely
Rolf
You have a circular dependancy with c.h including b.h and b.h including

c.h. This indicates a failure in OO analysis that will occur in any
language. Check out http://www.objectmentor.com/resources/articles/dip.pdf
--
Phil

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
John Potter
Guest





PostPosted: Sat Apr 10, 2004 6:22 pm    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote

On 10 Apr 2004 08:23:24 -0400, Stefan Slapeta
<stefan_nospam_ (AT) slapeta (DOT) com> wrote:

Quote:
Concerning your problem: if you want to pass objects (and not classes,
because classes are just definitions) by value like you did, you can't
just declare a forward reference like 'class A;' because the compiler
does not know the size of the object it should pass in this case.

The forward reference is sufficient to declare the receiving function.
The declaration is all that is needed in the header. The definition
will be needed in the implementation and any user.

Quote:
However, you never should pass objects by value, except there is a very
special reason for doing so!

The usual rule is the opposite. Pass everything by value unless there
is a special reason for doing otherwise.

if purpose of function is to modify the argument
pass by reference
else if type is huge
pass by reference to const
else
pass by value

Minimum access demands passing copies.

John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Stefan Slapeta
Guest





PostPosted: Sun Apr 11, 2004 10:16 am    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote

John Potter wrote:

Quote:
The forward reference is sufficient to declare the receiving function.
The declaration is all that is needed in the header. The definition
will be needed in the implementation and any user.


Oh, of course. Seems I misunderstood the problem in a hurry.

Quote:

The usual rule is the opposite. Pass everything by value unless there
is a special reason for doing otherwise.

if purpose of function is to modify the argument
pass by reference
else if type is huge
pass by reference to const
else
pass by value


Actually, I agree that it's not the best way _always_ to pass objects by
const ref. However, .... I wouldn't call this a 'rule' because for my
understanding, a rule is something like a formula. This one isn't
because 'the type is huge' is subjective and inprecise ('copying the
type is costly' would sound better for me in this context but it's even
more subjective and less measurable).

Furthermore, rules (except the ones in spirit grammars Smile always bear
the danger that someone generally applies them blindly [and stops
thinking himself]. This is very bad if the rule could also be
interpreted in many ways.

Quote:
Minimum access demands passing copies.

What exactly do you mean by 'minimum access'? Is it not giving the user
of a class the possibility to cast away 'const' and so being able to
modify the object? If yes, is this worth generally copying an object?


S.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ali Cehreli
Guest





PostPosted: Sun Apr 11, 2004 10:20 am    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote

Stephen Ludin <sludin_spam (AT) pacbell (DOT) net> wrote

Quote:
Rolf Hemmerling wrote:
#### C.h ###########
#ifndef C_H
#define C_H
#include "b.h"
class C { public:
void execute(B parameter);
};
#endif
[...]
Rather than passing the parameters by value, which requires the
compiler to see the declaration of the class, pass by const reference
which simply requires a forard declaration:

This is a common misconception. Pass-by-value does not require the
definitions of the parameter types. We can use forward declarations
even for them.

Quote:
For reference, this subject get exhaustive treatment in:
More Effective C++ (Meyers)
Large Scale C++ Software Design (Lakos)
Exceptional C++ (Sutter)

I am away from my copy of Exceptional C++ but I am quite sure that
Sutter mentions this in that book.

Indeed, I found a reference to this issue in Sutter's Guru of The Week
7:

http://www.gotw.ca/gotw/007.htm

This excerpted sentence doesn't make much sense out-of-context but
that's where I first heard about this fact:

"This also lets us get rid of c.h, since besides in X::clist_ C
objects only appear as parameters and return values."

Note: The 'c.h' in the sentence above has nothing to do with the
original poster's c.h. :)

Quote:

-stephen

Ali

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Rolf Hemmerling
Guest





PostPosted: Sun Apr 11, 2004 4:01 pm    Post subject: Re: ping-pong passing of instances Reply with quote

Hello !

First of all I would like to say thankyou to anybody answering me in
this thread.

My problem was solved ( in the REAL example and not just in the dummy
example presented here,

when I pushed some of the #include files at the BOTTOM of the .H file,
and in one case it was even necessary to put it into the .CPP file !

Quote:
Nope, sorry! - 2 Classes which instatiate each other is never a good
idea. I.e. this is what we call a 'cyclic dependency' and a very bad
design flaw in OO (not just in C++) and should be avoided under any
circumstances. (When you are more familiar with C++, I can recommend
reading John Lakos, 'Large Scale C++ Software Design'.)

The typical Modell-view-controller modell is like that, AFAIK.

you pass an instance of class#1 as (ref) parameter to an instance of
another class #2, and THIS second instance of class #2 calls a method of
the instance of the class #1 given as parameter, with "itself" ( =
pointer to instance of the class #2) as (ref) parameter.

So that the instance of #1 can call methods of #2, although #1 does not
generate a local instance of #2.

Learning about this ping-pong passing of instances was one of the most
challanging things for turning from procedural programming to oo thinking.


Sincerely
Rolf
--
/ / / Alone on the data highway...
/ / like on an allee in Hannover-Herrenhausen
/ / / The Hemmerling (R) WEB site - Rolf Hemmerling,Germany
/ / / http://www.hemmerling.com/


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
John Potter
Guest





PostPosted: Sun Apr 11, 2004 11:56 pm    Post subject: Re: Forwarding problem: 2 Classes have methods with instanze Reply with quote

On 11 Apr 2004 06:16:26 -0400, Stefan Slapeta
<stefan_nospam_ (AT) slapeta (DOT) com> wrote:

Quote:
The usual rule is the opposite. Pass everything by value unless there
is a special reason for doing otherwise.

if purpose of function is to modify the argument
pass by reference
else if type is huge
pass by reference to const
else
pass by value


Actually, I agree that it's not the best way _always_ to pass objects by
const ref. However, .... I wouldn't call this a 'rule' because for my
understanding, a rule is something like a formula. This one isn't
because 'the type is huge' is subjective and inprecise ('copying the
type is costly' would sound better for me in this context but it's even
more subjective and less measurable).

Actually, they are both measurable. Using the second case when a
profiler has not indicated a need is premature optimization. There are
those special cases where a copy will be required within the function
(push_back) and the reference to const is clearly superior. One copy
is better than two copies, but whether no copy is better than one
requires measurement.

Quote:
Minimum access demands passing copies.

What exactly do you mean by 'minimum access'? Is it not giving the user
of a class the possibility to cast away 'const' and so being able to
modify the object? If yes, is this worth generally copying an object?

Yes. See above.

There is a nice example in K&M, "Accelerated C++". A container is split
into two subsets. The container is received by reference and modified
using erase to produce the expected larger subset while the expected
smaller subset was produced locally using push_back and returned by
value. The example was used to show a case where a list was far
superior to a vector. I modified the example to receive the second
container by reference. Since it was a list, the whole thing could be
done using splice which is obviously much better. The time was reduced
by 3%. Hardly worth the trouble.

John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.