I'm reading C Primer, Lippman et. al. 5/e.
Section 7.5.2. Delegating Constructors says,
class Sales_data {
friend std::istream &read(std::istream&, Sales_data&);
public:
// nondelegating constructor initializes members from corresponding arguments
Sales_data(std::string s, unsigned cnt, double price):
bookNo(s), units_sold(cnt), revenue(cnt*price) { }
// remaining constructors all delegate to another constructor
Sales_data(): Sales_data("", 0, 0) {}
Sales_data(std::string s): Sales_data(s, 0,0) {}
Sales_data(std::istream &is): Sales_data()
{ read(is, *this); }
// other members as before
};
*In this version of Sales_data, all but one of the constructors delegate their work. The first constructor takes three arguments, uses those arguments to initialize the data members, and does no further work. In this version of the class, we define the default constructor to use the three-argument constructor to do its initialization. It too has no additional work, as indicated by the empty constructor body. The constructor that takes a string also delegates to the three-argument version.
The constructor that takes an istream& also delegates. It delegates to the default constructor, which in turn delegates to the three-argument constructor. Once those constructors complete their work, the body of the istream& constructor is run. Its constructor body calls read to read the given istream.*
Function read is defined in section 7.1.3 as follows,
// input transactions contain ISBN, number of copies sold, and sales price
istream &read(istream &is, Sales_data &item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
I'm confused about this line - Once those constructors complete their work, the body of the istream& constructor is run. Its constructor body calls read to read the given istream.
is this correct ?
IMO, read is a global function which is not called on any object. Please correct my understanding if wrong and please help me clarify my doubt.
CodePudding user response:
Yes, you get it right.
One easy way to find out the order of execution of constructors is to put a cout << "1" << endl; in one and "2" in anther and one in read().
CodePudding user response:
the istream& constructor
This is just a short-hand for "the constructor with a (single) parameter of type istream&
".
Suppose we give the constructors numbers:
/*1*/ Sales_data(std::string s, unsigned cnt, double price) //...
/*2*/ Sales_data(): Sales_data("", 0, 0) {}
/*3*/ Sales_data(std::string s): Sales_data(s, 0,0) {}
/*4*/ Sales_data(std::istream &is): Sales_data() //...
The quote is stating that a call to constructor 4 will first result in the execution of constructor 1 and 2 in that order before the body of 4 is executed.
The function body of constructor 4 contains a call to read
. This is what "constructor body calls read" refers to. This is a completely usual function call and not related to constructors.
So the quote is correct.
IMO, read is a global function which is not called on any object.
The quote is not using the language "called on", so I don't really know what you mean here, but note that the call to read
is not a call to a member function. There is no implicit object parameter involved like in a member function call of the form x.f()
. It is a completely normal free function call as you could also use in any expression outside a class context.