473,382 Members | 1,523 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

Just learning C++ - a question

I have created a class and used it to further overload ostream:

class drum
{
...
friend ostream& operator<< ( ostream&, drum const& );
}

ostream& operator<< ( ostream& out, drum const& od )
{
....
return out;
}

and this works great. Now I also realize that by passing the class
reference as a const, the called subroutine is prevented from writing
to 'drum' via compile time checking.

But just for giggles, I changed the declaration and definition by
omitting the 'const'. I received many compile errors and could not
quite follow what they meant.

So my question is, why does the reference to drum HAVE TO BE 'const' ??
Is that a quirk of my (gnu cygwin) compiler or ...

Thanks a million
Wick

Jul 31 '06 #1
12 1480

wickwire wrote:
So my question is, why does the reference to drum HAVE TO BE 'const' ??
Is that a quirk of my (gnu cygwin) compiler or ...
Maybe you are attempting to print a const drum? No way of knowing
without calling code.

Jul 31 '06 #2
wickwire wrote:
I have created a class and used it to further overload ostream:

class drum
{
...
friend ostream& operator<< ( ostream&, drum const& );
}

ostream& operator<< ( ostream& out, drum const& od )
{
....
return out;
}

and this works great. Now I also realize that by passing the class
reference as a const, the called subroutine is prevented from writing
to 'drum' via compile time checking.

But just for giggles, I changed the declaration and definition by
omitting the 'const'. I received many compile errors and could not
quite follow what they meant.

So my question is, why does the reference to drum HAVE TO BE 'const'
?? Is that a quirk of my (gnu cygwin) compiler or ...
It doesn't have to be const. The error messages you received were most
like due to the way you used your operator -- the object which you wanted
to output _was_ in fact a const object, probably. But as you see, I am
guessing here -- you didn't follow the recommendations of FAQ 5.8.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jul 31 '06 #3

Victor Bazarov wrote:
It doesn't have to be const. The error messages you received were most
like due to the way you used your operator -- the object which you wanted
to output _was_ in fact a const object, probably. But as you see, I am
guessing here -- you didn't follow the recommendations of FAQ 5.8.

OK, here is the code and error message:

************************************************** ***********************

#include <iostream>
#include <iomanip>

using namespace std;

class Base
{
public:
~Base(){}
Base(int val, int num) { }

friend ostream& operator<< ( ostream&, Base& );
};
ostream& operator<< ( ostream &os, Base& obj )
{
return os << "hi";
}
int main()
{
int u5 = 100;
cout << setw(0) << Base(u5,0) << endl;
return 0;
}

************************************************** ***********************
g++ o.cpp -o o
o.cpp: In function `int main()':
o.cpp:22: error: no match for 'operator<<' in 'std::operator<< [with
_CharT = char, _Traits =
std::char_traits<char>](((std::basic_ostream<char,
std::char_traits<char&)(&std::cout)), std::setw(0)) << Base(u5, 0)'

/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:63:
note: candidates are: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT,
_Traits>::operator<<(std::basic_ostream<_CharT,
_Traits>&(*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT =
char, _Traits = std::char_traits<char>]

/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:74:
note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(std::basic_ios<_CharT,
_Traits>&(*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char,
_Traits = std::char_traits<char>]

<<< The list of candidates is quite long >>>

Thanks
Wick

Jul 31 '06 #4

wickwire wrote:
cout << setw(0) << Base(u5,0) << endl;
You can't pass a temporary as a non-const parameter. Change to:

Base b(u5, 0);
cout << setw(0) << b << endl;

Jul 31 '06 #5

Noah Roberts wrote:
wickwire wrote:
cout << setw(0) << Base(u5,0) << endl;

You can't pass a temporary as a non-const parameter. Change to:

Base b(u5, 0);
cout << setw(0) << b << endl;
Thank you. A rule I was unfamiliar with. Do you mind one more question
?

Using the original code I supplied:
If I change the declaration and definition such that the passed
parameter IS a const (and this works ok as I stated before), is the
copy-constructor ever used ? I assume the constructor Base(int, int) is
all that is called (and the reference to the temporary object is passed
to ostream:: cout.

But if I add a copy-constructor to the Base object - and make it
private, I get an error message telling me that the constructor IS
private - if I add a copy-constructor to the object and make it public,
it never gets called.

Thanks again
Wick

Jul 31 '06 #6
In article <11**********************@i3g2000cwc.googlegroups. com>,
wi******@bigfoot.com says...

[ ... ]
ostream& operator<< ( ostream &os, Base& obj )
This takes a Base by reference, which means the parameter you pass
must be a non-const variable. To receive a temporary object, it must
receive a reference to a _const_ object:

ostream &operator<<(ostream &os, Base const &obj) { /* ... */ }

A reference parameter should normally be a reference to a const
object unless the function really needs to modify the original object
-- and you probably do NOT want an operator<< to modify the original
object.

[ ... ]
cout << setw(0) << Base(u5,0) << endl;
Here, instead of passing a non-const variable, you're passing a
temporary object. Since that can only bind to a reference to const,
and you don't have an operator<< that takes a reference to a const
Base, the compiler complains that it can't find a suitable function
to use (and, in this case, lists what it looked at that wouldn't
work).

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jul 31 '06 #7

Jerry Coffin wrote:
In article <11**********************@i3g2000cwc.googlegroups. com>,
wi******@bigfoot.com says...

[ ... ]
ostream& operator<< ( ostream &os, Base& obj )

This takes a Base by reference, which means the parameter you pass
must be a non-const variable. To receive a temporary object, it must
receive a reference to a _const_ object:

ostream &operator<<(ostream &os, Base const &obj) { /* ... */ }

A reference parameter should normally be a reference to a const
object unless the function really needs to modify the original object
-- and you probably do NOT want an operator<< to modify the original
object.
Thanks for a simple answer. This all makes sense now - from a rules
perspective, although I am not sure I understand WHY the limitations
are there yet. And actually, I did want the operator<< to modify the
original object, which is why I got into this issue in the first place
(no profound reason, just playing around).

Wick

Jul 31 '06 #8
In article <11**********************@i3g2000cwc.googlegroups. com>,
wi******@bigfoot.com says...

[ A non-const reference can't bind to a temporary ... ]
Thanks for a simple answer. This all makes sense now - from a rules
perspective, although I am not sure I understand WHY the limitations
are there yet.
A couple of reasons. One is that it gives the compiler some leeway in
how it does things. For example, rather than creating each temporary
object on the fly, the compiler could pre-build all the temporary
objects, and then just use them when needed. If you allowed them to
be modified, the next time you re-used that temporary object, you
wouldn't get what you expected.
And actually, I did want the operator<< to modify the
original object, which is why I got into this issue in the first place
(no profound reason, just playing around).
While it's perfectly reasonable when you're just playing around, for
real code, careful judgement is important. Overloading operators to
do things a lot different from what people expect is generally a poor
idea. You could overload operator+ to do multiplication and operator*
to do subtraction, but it would usually be a really _bad_ idea.

Likewise with overloading operator<< to modify its argument. This
would surprise people enough that it's almost certain to be a bad
idea.

As an aside, what does it accomplish for it to modify its argument,
if that argument is a temporary? The new value you've created will be
discarded at the end of the expression anyway...

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jul 31 '06 #9

Jerry Coffin wrote:
In article <11**********************@i3g2000cwc.googlegroups. com>,
wi******@bigfoot.com says...

As an aside, what does it accomplish for it to modify its argument,
if that argument is a temporary? The new value you've created will be
discarded at the end of the expression anyway...
In this case, I was building a binary number operator for ostream and
as I was peeling the bits off of the passed value, I was shifting the
number <in a variable in the object>. So in effect I was simply using a
variable in the object when an automatic variable in the function would
have been a better choice.

Enjoy,
Wick

Jul 31 '06 #10

wickwire wrote:
Noah Roberts wrote:
wickwire wrote:
cout << setw(0) << Base(u5,0) << endl;
You can't pass a temporary as a non-const parameter. Change to:

Base b(u5, 0);
cout << setw(0) << b << endl;

Thank you. A rule I was unfamiliar with. Do you mind one more question
?

Using the original code I supplied:
If I change the declaration and definition such that the passed
parameter IS a const (and this works ok as I stated before), is the
copy-constructor ever used ? I assume the constructor Base(int, int) is
all that is called (and the reference to the temporary object is passed
to ostream:: cout.

But if I add a copy-constructor to the Base object - and make it
private, I get an error message telling me that the constructor IS
private - if I add a copy-constructor to the object and make it public,
it never gets called.
I don't know why the copy-ctr is wanted. If the standard says a copy
takes place then the copy ctr must be available. However, the standard
does say that an implementation is free not to copy in some cases as an
optimization technique so then maybe the ctr has to be there but
doesn't have to be called.

I don't know the actual answer to your question. That's just a guess
about what might be going on.

Jul 31 '06 #11

Noah Roberts wrote:
wickwire wrote:
Noah Roberts wrote:
wickwire wrote:
I don't know why the copy-ctr is wanted. If the standard says a copy
takes place then the copy ctr must be available. However, the standard
does say that an implementation is free not to copy in some cases as an
optimization technique so then maybe the ctr has to be there but
doesn't have to be called.

I don't know the actual answer to your question. That's just a guess
about what might be going on.
Thanks for trying to answer this one. I did find another post that
asked a similar question and the answer was that the compiler needed
the ctor (so it had to be public) and then optimised it away (so it
never got called). That seems to describe the bahavior I see although
why a copy-ctor would be needed in the first place is still a mystery.

See, I'm learning a lot from this group. I'm already using 'ctor'
instead of 'constructor' !

Wick

Jul 31 '06 #12

wickwire wrote:
Noah Roberts wrote:
wickwire wrote:
Noah Roberts wrote:
wickwire wrote:
I don't know why the copy-ctr is wanted. If the standard says a copy
takes place then the copy ctr must be available. However, the standard
does say that an implementation is free not to copy in some cases as an
optimization technique so then maybe the ctr has to be there but
doesn't have to be called.

I don't know the actual answer to your question. That's just a guess
about what might be going on.

Thanks for trying to answer this one. I did find another post that
asked a similar question and the answer was that the compiler needed
the ctor (so it had to be public) and then optimised it away (so it
never got called). That seems to describe the bahavior I see although
why a copy-ctor would be needed in the first place is still a mystery.
It has to do with the assignment of the temporary to a reference. The
reference has to be const (as the return of a function/constructor is
not an lvalue) and a copy occurs.

The implementation is free to optimize out the copy but all semantic
requirements must be met. In other words the constructor must exist.

I just looked it up in the std...many references, I couldn't quote it
all here but that is the gist of the matter. The standard is really a
must have for anyone serious about really knowing what they are doing
in C++.

Jul 31 '06 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: James White | last post by:
I have a young nephew who appears to be developing into a natural geek/nerd/guru/whatever and as he learns I need to make sure that he stays on the side of the white hats, rather than going down...
13
by: Lumpierbritches | last post by:
I'm curious as to why some questions posted here get results and solutions, while others are answered in a seemingly foreign language and I can't begin to comprehend or understand the answers that...
36
by: utab | last post by:
Dear, I have experince in C( numerical projects, like engineering problems, scientific applications) I have the basic notion of C++ also, I have read Accelerated C++ until Chapter 7, however it...
7
by: Michael | last post by:
Hey, I'm, I guess, an itermediate programmer and I have a question about learning any programming language. I understand that as a programmer you're going to probably constantly be re-writing code...
5
by: Hasin Hayder | last post by:
I have been working with PHP for more than 3yrs (I believe still I am beginner in this category) - I was present in several interview board. Which things disappointed me most is the "lack of...
21
by: shotokan99 | last post by:
guys, i read in some forums that php is just for hobbiest, and is not suited for some serius and heavy application. for robust and hi performance application asp.net or jsp is the way to go. how...
5
by: romiro | last post by:
Hi all, I'm a PHP5 developer looking to "broaden my horizons" so to speak by learning a new language. I emphasize the 5 in PHP since I have fully engrossed myself in the full OOP of version 5...
2
by: lmaurer | last post by:
Hi all, I have been charged with learning how to create web pages that will function as data capturing tools. From the research I have done, it looks like I need to learn ASP.net and SQL Server...
5
by: Beany | last post by:
Hi All, I keep asking myself the question whether i'm doing the right thing learning Perl? I'm new to Perl (as you can see from my posts) and want to become a programmer in the near future.....
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.