 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Rolf Hemmerling Guest
|
Posted: Fri Apr 09, 2004 1:32 pm Post subject: Forwarding problem: 2 Classes have methods with instanze of |
|
|
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
|
Posted: Sat Apr 10, 2004 11:14 am Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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
|
Posted: Sat Apr 10, 2004 11:18 am Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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
|
Posted: Sat Apr 10, 2004 11:23 am Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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
|
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
|
Posted: Sat Apr 10, 2004 11:25 am Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
Rolf Hemmerling wrote:
[...]
it did NOT help to put any "forwarding class declarations" [...]
in the head of the files
[...]
Hi,
it alone wouldn't help, if the two headers continue to include the other
one, causing an infinite recursion 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
|
Posted: Sat Apr 10, 2004 11:25 am Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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
|
Posted: Sat Apr 10, 2004 12:10 pm Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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
|
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. First let's see the first
thing. (I read Alice in Wonderland )
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;
+-+
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
|
Posted: Sat Apr 10, 2004 12:23 pm Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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
|
Posted: Sat Apr 10, 2004 12:26 pm Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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
|
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
|
Posted: Sat Apr 10, 2004 1:56 pm Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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
|
Posted: Sat Apr 10, 2004 6:22 pm Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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
|
Posted: Sun Apr 11, 2004 10:16 am Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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 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
|
Posted: Sun Apr 11, 2004 10:20 am Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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. :)
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
|
Posted: Sun Apr 11, 2004 4:01 pm Post subject: Re: ping-pong passing of instances |
|
|
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
|
Posted: Sun Apr 11, 2004 11:56 pm Post subject: Re: Forwarding problem: 2 Classes have methods with instanze |
|
|
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 |
|
 |
|
|
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
|
|