C++/concise explanation to this code..
Expert: vijayan - 2/17/2010
QuestionQUESTION: hello Vijayan,
i was studying a c++ code that demonstrates the increment both prefix and postfix operator but i was abit confused about certain statements in the code. please, clarify me more on each one of them. below is the code:
#include <iostream>
#include <stdexcept>
using namespace std;
class Time
{
int min;
int hr;
public:
Time(int _hr, int _min) : min( _min ), hr( _hr )
{
if( ( hr >= 0 && hr < 24 ) || ( min >= 0 && min < 24 ) )
throw std::range_error( "incorrect time" ) ;
}
enum { MINUTES_PER_DAY = 60 * 24 } ;
explicit Time( int _asMin = 0 )
{
if( ( _asMin < 0 ) || ( _asMin >= MINUTES_PER_DAY ) )
throw std::range_error( "incorrect time" ) ;
hr = _asMin/60; min = _asMin%60 ;
};
friend ostream &operator<<(ostream &out, const Time &t2);
friend istream &operator>>(istream &in, Time &t2);
Time operator++(int); //postfix increment
Time& operator++(); //prefix increment
int getTmin(){return hr*60 + min;}
// etc
};
Time Time::operator++(int)
{
Time old = *this;
*this = Time( ( getTmin() + 1 ) % Time::MINUTES_PER_DAY );
return old;
}
Time& Time::operator++()
{
*this = Time( ( getTmin() + 1 ) % Time::MINUTES_PER_DAY );
return *this;
}
ostream &operator<<(ostream &out, const Time& t2 )
{ return out << t2.hr << ' ' << t2.min ; }
istream &operator>> ( istream &in, Time& t2 )
{
int hr, min ;
if( ( in >> hr >> min ) &&
( hr >= 0 && hr < 24 ) && ( min >= 0 && min < 60 ) )
{
t2.hr = hr ;
t2.min = min ;
}
else in.clear( ios::failbit ) ; // set stream to failed state
return in ;
}
int main(void)
{
Time time;
cout << "Enter time :" ;
cin >> time;
cout << time++ << '\n' ;
cout << ++time << '\n' ;
system("PAUSE");
return(0);
}
questions:
1. how many constructor is the Time class using? i seen one normal Time(int _hr, int _min) constructor but there is also the explicit Time() pls what is the explicit Time(int _asMin = 0) function doing there.
2.In the prefix operator function: Time operator++(int);
there is this statement :
Time old = *this;
*this = Time( ( getTmin() + 1 ) % Time::MINUTES_PER_DAY );
return old;
why are we interested in setting the *this pointer to the Time old? Also, why is the MINUTES_PER_DAY enum accessed using the scope Time::MINUTES_PER_DAY? is it because MINUTES_PER_DAY is an enumerated variable?
These are my confusion. i hope to get a clearer understanding of this code after this questions are answered. thanks alot.
ANSWER: > how many constructor is the Time class using? i seen one normal Time(int _hr, int _min) constructor but there is also the explicit Time() pls what is the explicit Time(int _asMin = 0) function doing there.
class Time has two constructors;
Time(int _hr, int _min) : min( _min ), hr( _hr ) ;
explicit Time( int _asMin = 0 ) ;
A class can have as many constructors as we want; constructors can be overloaded.
For the meaning and rationale of the explicit keyword, see:
http://weblogs.asp.net/kennykerr/archive/2004/08/31/Explicit-Constructors.aspx
> why are we interested in setting the *this pointer to the Time old?
The result of post-fix increment operator i++ ods the value of i *before* it is incremented. this is a pointer to the Time being incremented, *this dereferences the pointer to get a reference to the Time that is being incremented.
Time old = *this ;
therefore makes a copy of the Time object *before* it is incremented. This copy (old) is what is returned as the result of the operation.
> why is the MINUTES_PER_DAY enum accessed using the scope Time::MINUTES_PER_DAY? is it because MINUTES_PER_DAY is an enumerated variable?
The enumerated value MINUTES_PER_DAY is within the class Time (not at the global scope). So the scope has to be given using the scope resolution operator (::). Time::MINUTES_PER_DAY means the MINUTES_PER_DAY defined within Time (and not anywhere else).
---------- FOLLOW-UP ----------
QUESTION: why are these two functions different and how does the const. affect them?
const float& Array::operator[] (int i) const
{
return c_array[i];
}
float& Array::operator[] (int i)
{
return c_array[i];
}
ANSWER: Let us say we have a function:
void our_function( const Array& const_arr, Array& arr )
{
std::cout << const_arr[3] << '\n' ;
// const_arr is a const Array; this calls const float& Array::operator[] (int i) const
// we can inspect the element, but cannot modify it since we get a reference to a float that is const
arr[3] = 5.76f ;
// arr is a non-const Array; this calls float& Array::operator[] (int i)
// we can inspect the element, and can also modify it since we get a reference to a float that is non-const
}
In this function, the const_arr is a constant (non-mutable) object, we should not be able to modify it. The elements of const_arr can be accessed by us, but cannot modified.
arr is a non-const (mutable) object; we should be able to modify its contents. The elements of arr can be accessed by us, and we can also modify them.
Also see:
http://www.parashift.com/c++-faq-lite/const-correctness.html
It is worthwhile reading all the FAQs in this section.
FAQ
http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.12 deals specifically with your question.
---------- FOLLOW-UP ----------
QUESTION: hello,
i was really looking to see a small code that justifies this. such that if i try to modify it, i get a compiler error because the first method is a const reference to float while if i try to use the mutable method, it works. thatz what i was looking for. something to try and see for myself and help me remember ..
hope you can do that for me.
thanks
AnswerTry compiling this code:
struct int_array_10
{
int_array_10() { for( int i=0 ; i<10 ; ++i ) a[i] = i ; }
int& operator[] ( int pos ) { return a[pos] ; }
const int& operator[] ( int pos ) const { return a[pos] ; }
private : int a[10] ;
};
void function( int_array_10& a, const int_array_10& ca )
{
int i = a[5] ; // fine
a[5] = 12345 ; // fine, a is modifiable, every element of a is therefore modifiable
i = ca[5] ; // fine, we are not trying to modify ca
ca[5] = 12345 ; // **** error: can't modify a const int
// ca is non-modifiable; an element of ca is therefore non-modifiable
}