Please indicate the source: http://blog.csdn.net/gaoxiangnumber1
Welcome to my github: https://github.com/gaoxiangnumber1
operator
followed by the symbol for the operator being defined. An overloaded operator has a return type, a parameter list, and a body.Calling an Overloaded Operator Function Directly
// equivalent calls to a nonmember operator function
data1 + data2; // normal expression
operator+(data1, data2); // equivalent function call
data1 += data2; // expression-based ''call''
data1.operator+=(data2); // equivalent call to a member operator function
Some Operators Shouldn’t Be Overloaded
Use Definitions That Are Consistent with the Built-in Meaning
Assignment and Compound Assignment Operators
Choosing Member or Nonmember Implementation
string s = "world";
string t = s + "!"; // ok: we can add a const char* to a string
string u = "hi" + s; // ok, but would be an error if + were a member of string
string x = "hi" + "!"; // error: at least one of the operands has a class type
"hi" + s
is equivalent to operator+("hi", s)
. The only requirements are that at least one of the operands has a class type, and that both operands can be converted to string.In what ways does an overloaded operator differ from a built-in operator? In what ways are overloaded operators the same as the built-in operators?
Write declarations for the overloaded input, output, addition, and compound-assignment operators for Sales_data.
istream &operator>>(istream &, Sales_data &);
ostream &operator<<(ostream &, const Sales_data &);
Sales_data operator+(const Sales_data &, const Sales_data &);
Sales_data::Sales_data &operator+=(const Sales_data &);
Both string and vector define an overloaded == that can be used to compare objects of those types. Assuming svec1 and svec2 are vectors that hold strings, identify which version of == is applied in each of the following expressions:
(a) “cobble” == “stone”
(b) svec1[0] == svec2[0]
(c) svec1 == svec2
(d) svec1[0] == “stone”
Explain how to decide whether the following should be class members:
(a) %
(b) %=
(c) ++
(d) ->
(e) <<
(f) &&
(g) ==
(h)()
In exercise 7.40 from 7.5.1(p. 291) you wrote a sketch of one of the following classes. Decide what, if any, overloaded operators your class should provide.
(a) Book
(b) Date
(c) Employee
(d) Vehicle
(e) Object
(f) Tree
The Sales_data Output Operator
ostream &operator<<(ostream &os, const Sales_data &item)
{
os << item.isbn() << ' ' << item.units_sold << ' ' << item.revenue <<
' ' << item.avg_price() << '\n';
return os;
}
Output Operators Usually Do Minimal Formatting
IO Operators Must Be Nonmember Functions
Sales_data data;
data << cout; // if operator<< is a member of Sales_data
Define an output operator for your Sales_data class.
ostream &operator<<(ostream &os, const Sales_data &item)
{
os << item.isbn() << ' ' << item.units_sold << ' ' << item.revenue <<
' ' << item.avg_price();
return os;
}
Define an output operator for String class you wrote for the exercises in 13.5(p. 531).
ostream& operator<<(ostream &os, const String &s)
{
char *c = const_cast<char*>(s.c_str());
while(*c)
{
os << *c++;
}
return os;
}
Define an output operator for the class you chose in exercise 7.40 from 7.5.1(p. 291).
ostream& operator<<(ostream& os, const Book& book)
{
os << book.no_ << " " << book.name_ << " " << book.author_ << " "
<< book.pubdate_;
return os;
}
The Sales_data Input Operator
istream& operator>>(istream &is, Sales_data &item)
{
double price; // no need to initialize; we'll read into price before we use it
is >> item.bookNo >> item.units_sold >> price;
if(is) // check that the inputs succeeded
{
item.revenue = price * item.units_sold;
}
else
{
item = Sales_data(); // input failed: give the object the default state
}
return is;
}
Errors during Input
Indicating Errors
Define an input operator for your Sales_data class.
istream& operator>>(istream &is, Sales_data &item)
{
double price; // no need to initialize; we'll read into price before we use it
is >> item.bookNo >> item.units_sold >> price;
if(is) // check that the inputs succeeded
{
item.revenue = price * item.units_sold;
}
else
{
item = Sales_data(); // input failed: give the object the default state
}
return is;
}
Describe the behavior of the Sales_data input operator if given the following input:
(a) 0-201-99999-9 10 24.95
(b) 10 24.95 0-210-99999-9
What, if anything, is wrong with the following Sales_data input operator? What would happen if we gave this operator the data in the previous exercise?
istream& operator>>(istream& in, Sales_data& s)
{
double price;
in >> s.bookNo >> s.units_sold >> price;
s.revenue = s.units_sold * price;
return in;
}
Define an input operator for the class you used in exercise 7.40 from 7.5.1(p. 291). Be sure the operator handles input errors.
// assumes that both objects refer to the same book
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs; // copy data members from lhs into sum
sum += rhs; // add rhs into sum
return sum;
}
Which other arithmetic operators(Table 4.1(p. 139)), if any, do you think Sales_data ought to support? Define any you think the class should include.
Why do you think it is more efficient to define operator+ to call operator+= rather than the other way around?
Should the class you chose for exercise 7.40 from 7.5.1(p. 291) define any of the arithmetic operators? If so, implement them. If not, explain why not.
bool operator==(const Sales_data &lhs, const Sales_data &rhs)
{
return lhs.isbn() == rhs.isbn() &&
lhs.units_sold == rhs.units_sold &&
lhs.revenue == rhs.revenue;
}
bool operator!=(const Sales_data &lhs, const Sales_data &rhs)
{
return !(lhs == rhs);
}
operator==
rather than as a named function.Define equality and inequality operators for your StrBlob
(12.1.1, p. 456), StrBlobPtr(12.1.6, p. 474), StrVec(13.5, p. 526), and String(13.5, p. 531) classes.
Should the class you chose for exercise 7.40 from 7.5.1(p. 291) define the equality operators? If so, implement them. If not, explain why not.
Define relational operators for your StrBlob, StrBlobPtr, StrVec, and String classes.
Should the class you chose for exercise 7.40 from 7.5.1(p. 291) define the relational operators? If so, implement them. If not, explain why not.
class StrVec
{
public:
StrVec &operator=(std::initializer_list<std::string>);
// other members as in § 13.5 (p. 526)
};
StrVec &StrVec::operator=(initializer_list<string> il)
{
// alloc_n_copy allocates space and copies elements from the given range
auto data = alloc_n_copy(il.begin(), il.end());
free(); // destroy the elements in this object and free the space
elements = data.first; // update data members to point to the new space
first_free = cap = data.second;
return *this;
}
Compound-Assignment Operators
// member binary operator: left-hand operand is bound to the implicit this pointer
// assumes that both objects refer to the same book
Sales_data& Sales_data::operator+=(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
Define the addition and compound-assignment operators for your Sales_data class.
Write the Sales_data operators so that + does the actual addition and += calls +. Discuss the disadvantages of this approach compared to the way these operators were defined in 14.3(p. 560) and 14.4(p. 564).
Sales_data& Sales_data::operator+=(const Sales_data &rhs)
{
Sales_data old_data = *this;
*this = old_data + rhs;
return *this;
}
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum;
sum.units_sold = lhs.units_sold + rhs.units_sold;
sum.revenue = lhs.revenue + rhs.revenue;
return sum;
}
Define a version of the assignment operator that can assign a string representing an ISBN to a Sales_data.
Define an initializer_list assignment operator for your version of the StrVec class.
Decide whether the class you used in exercise 7.40 from 7.5.1(p. 291) needs a copy- and move-assignment operator. If so, define those operators.
Implement any other assignment operators your class should define. Explain which types should be used as operands and why.
class StrVec
{
public:
std::string& operator[](std::size_t n)
{
return elements[n];
}
const std::string& operator[](std::size_t n) const
{
return elements[n];
}
// other members as in § 13.5 (p. 526)
private:
std::string *elements; // pointer to the first element in the array
};
// assume svec is a StrVec
const StrVec cvec = svec; // copy elements from svec into cvec
// if svec has any elements, run the string empty function on the first one
if (svec.size() && svec[0].empty())
{
svec[0] = "zero"; // ok: subscript returns a reference to a string
cvec[0] = "Zip"; // error: subscripting cvec returns a reference to const
}
Define subscript operators for your StrVec, String, StrBlob, and StrBlobPtr classes.
Defining Prefix Increment/Decrement Operators
class StrBlobPtr
{
public:
// increment and decrement
StrBlobPtr& operator++(); // prefix operators
StrBlobPtr& operator--();
// other members as before
};
// prefix: return a reference to the incremented/decremented object
StrBlobPtr& StrBlobPtr::operator++()
{
// if curr already points past the end of the container, can't increment it
check(curr, "increment past end of StrBlobPtr");
++curr; // advance the current state
return *this;
}
StrBlobPtr& StrBlobPtr::operator--()
{
// if curr is zero, decrementing it will yield an invalid subscript
--curr; // move the current state back one element
check(curr, "decrement past begin of StrBlobPtr");
return *this;
}
// check returns a shared_ptr to the vector if the check succeeds
shared_ptr<vector<string>> check(size_t i, const string &msg) const
{
shared_ptr<vector<string>> ret = wptr.lock();
if(!ret)
{
throw runtime_error("unbound StrBlobPtr");
}
if(i >= ret->size())
{
throw out_of_range(msg);
}
return ret;
}
Differentiating Prefix and Postfix Operators
class StrBlobPtr
{
public:
// increment and decrement
StrBlobPtr operator++(int); // postfix operators
StrBlobPtr operator--(int);
// other members as before
};
// postfix: increment/decrement the object but return the unchanged value
StrBlobPtr StrBlobPtr::operator++(int)
{
// no check needed here; the call to prefix increment will do the check
StrBlobPtr ret = *this; // save the current value
++*this; // advance one element; prefix ++ checks the increment
return ret; // return the saved state
}
StrBlobPtr StrBlobPtr::operator--(int)
{
// no check needed here; the call to prefix decrement will do the check
StrBlobPtr ret = *this; // save the current value
--*this; // move backward one element; prefix -- checks the decrement
return ret; // return the saved state
}
Calling the Postfix Operators Explicitly
StrBlobPtr p(a1); // p points to the vector inside a1
p.operator++(0); // call postfix operator++
p.operator++(); // call prefix operator++
Add increment and decrement operators to your StrBlobPtr class.
Define addition and subtraction for StrBlobPtr so that these operators implement pointer arithmetic(3.5.3, p. 119).
We did not define a const version of the increment and decrement operators. Why not?
class StrBlobPtr
{
public:
std::string& operator*() const
{
auto p = check(curr, "dereference past end");
return (*p)[curr]; // (*p) is the vector to which this object points
}
std::string* operator->() const
{
// delegate the real work to the dereference operator
return & this->operator*();
}
// other members as before
};
StrBlob a1 = {"hi", "bye", "now"};
StrBlobPtr p(a1); // p points to the vector inside a1
*p = "okay"; // assigns to the first element in a1
cout << p->size() << endl; // prints 4, the size of the first element in a1
cout << (*p).size() << endl; // equivalent to p->size()
Constraints on the Return from Operator Arrow
point->mem
, point must be a pointer to a class object or an object of a class with an overloaded operator->. point->mem
is equivalent to(*point).mem; // point is a built-in pointer type
point.operator()->mem; // point is an object of class type
Add dereference and arrow operators to your StrBlobPtr class and to the ConstStrBlobPtr class that you defined in exercise 12.22 from 12.1.6(p. 476). Note that the operators in constStrBlobPtr must return const references because the data member in constStrBlobPtr points to a const vector.
Our StrBlobPtr class does not define the copy constructor, assignment operator, or a destructor. Why is that okay?
Define a class that holds a pointer to a StrBlobPtr. Define the overloaded arrow operator for that class.
struct absInt
{
int operator()(int val) const
{
return val < 0 ? -val : val;
}
};
int i = -42;
absInt absObj; // object that has a function-call operator
int ui = absObj(i); // passes i to absObj.operator()
Function-Object Classes with State
class PrintString
{
public:
PrintString(ostream &o = cout, char c = ' '): os(o), sep(c) {}
void operator()(const string &s) const
{
os << s << sep;
}
private:
ostream &os; // stream on which to write
char sep; // character to print after each output
};
PrintString printer; // uses the defaults; prints to cout
printer(s); // prints s followed by a space on cout
PrintString errors(cerr, '\n');
errors(s); // prints s followed by a newline on cerr
for_each(vs.begin(), vs.end(), PrintString(cerr, '\n'));
How many operands may an overloaded function-call operator take?
Define a function-object class to perform an if-then-else operation: The call operator for this class should take three parameters. It should test its first parameter and if that test succeeds, it should return its second parameter; otherwise, it should return its third parameter.
#include <iostream>
using namespace std;
struct Choose
{
int operator()(int a, int b, int c)
{
return a != 0 ? b : c;
}
};
int main()
{
Choose obj;
cout << obj(1, 2, 3) << '\n'; // 2
cout << obj(0, -1, 1); // 1
return 0;
}
Write a class like PrintString that reads a line of input from an istream and returns a string representing what was read. If the read fails, return the empty string.
#include <iostream>
using namespace std;
struct Print
{
string operator()(istream &is = cin)
{
string ret;
if(is >> ret)
{
return ret;
}
return string();
}
};
int main()
{
Print obj;
cout << obj();
return 0;
}
Use the class from the previous exercise to read the standard input, storing each line as an element in a vector.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Print
{
string operator()(istream &is = cin)
{
string ret;
getline(is, ret);
return is ? ret : string();
}
};
int main()
{
Print obj;
string str = obj(cin);
vector<string> vec;
while(!str.empty())
{
vec.push_back(str);
str = obj(cin);
}
for(auto s : vec)
{
cout << s << '\n';
}
return 0;
}
Write a class that tests whether two values are equal. Use that object and the library algorithms to write a program to replace all instances of a given value in a sequence.
plus<int> intAdd; // function object that can add two int values
negate<int> intNegate; // function object that can negate an int value
// uses intAdd::operator(int, int) to add 10 and 20
int sum = intAdd(10, 20); // equivalent to sum = 30
sum = intNegate(intAdd(10, 20)); // equivalent to sum = 30
// uses intNegate::operator(int) to generate -10 as the second parameter
// to intAdd::operator(int, int)
sum = intAdd(10, intNegate(10)); // sum = 0
Using a Library Function Object with the Algorithms
// passes a temporary function object that applies the < operator to two strings
sort(svec.begin(), svec.end(), greater<string>());
vector<string*> nameTable; // vector of pointers
// error: the pointers in nameTable are unrelated, so < is undefined
sort(nameTable.begin(), nameTable.end(), [](string *a, string *b) { return a < b; });
// ok: library guarantees that less on pointer types is well defined
sort(nameTable.begin(), nameTable.end(), less<string*>());
Using library function objects and adaptors, define an expression to
(a) Count the number of values that are greater than 1024
(b) Find the first string that is not equal to pooh
(c) Multiply all values by 2
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <functional>
int main()
{
using std::placeholders::_1;
std::vector<int> ivec { 1, 111, 1111, 11111 };
int count = std::count_if (ivec.cbegin(), ivec.cend(), std::bind(std::greater<int>(), _1, 1024));
std::cout << count << std::endl;
std::vector<std::string> svec { "pooh", "pooh", "pezy", "pooh" };
auto found = std::find_if (svec.cbegin(), svec.cend(), std::bind(std::not_equal_to<std::string>(), _1, "pooh"));
std::cout << *found << std::endl;
std::transform(ivec.begin(), ivec.end(), ivec.begin(), std::bind(std::multiplies<int>(), _1, 2));
for (int i : ivec) std::cout << i << " ";
std::cout << std::endl;
}
Using library function objects, determine whether a given int value is divisible by any element in a container of ints.
#include <iostream>
#include <string>
#include <functional>
#include <algorithm>
int main()
{
auto data = { 2, 3, 4, 5 };
int input;
std::cin >> input;
std::modulus<int> mod;
auto predicator = [&](int i)
{
return 0 == mod(input, i);
};
auto is_divisible = std::any_of(data.begin(), data.end(), predicator);
std::cout << (is_divisible ? "Yes!" : "No!") << std::endl;
return 0;
}
int(int, int)
is a function type that takes two ints and returns an int.Different Types Can Have the Same Call Signature
// ordinary function
int add(int i, int j)
{
return i + j;
}
// lambda, which generates an unnamed function-object class
auto mod = [](int i, int j)
{
return i % j;
};
// function-object class
struct div
{
int operator()(int denominator, int divisor)
{
return denominator / divisor;
}
};
int(int, int)
// maps an operator to a pointer to a function taking two ints and returning an int map<string, int(*)(int,int)> binops;
- But we can’t store mod or div in binops:
```cpp
binops.insert({"%", mod}); // error: mod is not a pointer to function
<div class="se-preview-section-delimiter"></div>
The Library function Type
function
that is defined in . Table 14.3 lists the operations defined by function.function<int(int, int)>
function<int(int, int)> f1 = add; // function pointer
function<int(int, int)> f2 = div(); // object of a function-object class
function<int(int, int)> f3 = [](int i, int j) // lambda
{
return i * j;
};
cout << f1(4,2) << endl; // prints 6
cout << f2(4,2) << endl; // prints 2
cout << f3(4,2) << endl; // prints 8
<div class="se-preview-section-delimiter"></div>
// table of callable objects corresponding to each binary operator
// all the callables must take two ints and return an int
// an element can be a function pointer, function object, or lambda
map<string, function<int(int, int)>> binops =
{
{"+", add}, // function pointer
{"-", std::minus<int>()}, // library function object
{"/", div()}, // user-defined function object
{"*", [](int i, int j) { return i * j; }}, // unnamed lambda
{"%", mod} // named lambda object
};
<div class="se-preview-section-delimiter"></div>
binops["+"](10, 5); // calls add(10, 5)
binops["-"](10, 5); // uses the call operator of the minus<int> object
binops["/"](10, 5); // uses the call operator of the div object
binops["*"](10, 5); // calls the lambda function object
binops["%"](10, 5); // calls the lambda function object
<div class="se-preview-section-delimiter"></div>
Overloaded Functions and function
int add(int i, int j)
{
return i + j;
}
Sales_data add(const Sales_data&, const Sales_data&);
map<string, function<int(int, int)>> binops;
binops.insert( {"+", add} ); // error: which add?
<div class="se-preview-section-delimiter"></div>
int(*fp)(int,int) = add; // pointer to the version of add that takes two ints
binops.insert({"+", fp} ); // ok: fp points to the right version of add
<div class="se-preview-section-delimiter"></div>
// ok: use a lambda to disambiguate which version of add we want to use
binops.insert({"+", [](int a, int b) {return add(a, b);} } );
<div class="se-preview-section-delimiter"></div>
Write your own version of a simple desk calculator that can handle binary operations.
<div class="se-preview-section-delimiter"></div>
#include <iostream>
<div class="se-preview-section-delimiter"></div>
#include <string>
<div class="se-preview-section-delimiter"></div>
#include <map>
<div class="se-preview-section-delimiter"></div>
#include <functional>
using namespace std;
int add(int i, int j)
{
return i + j;
}
auto mod = [](int i, int j)
{
return i % j;
};
struct Div
{
int operator ()(int i, int j) const
{
return i / j;
}
};
map<string, function<int(int, int)>> binops =
{
{ "+", add }, // function pointer
{ "-", minus<int>() }, // library functor
{ "/", Div() }, // user-defined functor
{ "*", [](int i, int j) { return i*j; }}, // unnamed lambda
{ "%", mod } // named lambda object
};
int main()
{
while(1)
{
cout << "Input: operand1 operator operand2\n";
int lhs, rhs;
string op;
cin >> lhs >> op >> rhs;
cout << binops[op](lhs, rhs) << endl;
}
return 0;
}
<div class="se-preview-section-delimiter"></div>
operator type() const;
.Defining a Class with a Conversion Operator
class SmallInt
{
public:
SmallInt(int i = 0): val(i)
{
if (i < 0 || i > 255)
throw std::out_of_range("Bad SmallInt value"); // <stdexcept>
}
operator int() const
{
return val;
}
private:
std::size_t val;
};
<div class="se-preview-section-delimiter"></div>
SmallInt si;
si = 4; // implicitly converts 4 to SmallInt then calls SmallInt::operator=
si + 3; // implicitly converts si to int followed by integer addition
<div class="se-preview-section-delimiter"></div>
// the double argument is converted to int using the built-in conversion
SmallInt si = 3.14; // calls the SmallInt(int) constructor
// the SmallInt conversion operator converts si to int;
si + 3.14; // that int is converted to double using the built-in conversion
<div class="se-preview-section-delimiter"></div>
class SmallInt;
operator int(SmallInt&); // error: nonmember
class SmallInt
{
public:
int operator int() const; // error: return type
operator int(int = 0) const; // error: parameter list
operator int*() const
{
return 42; // error: 42 is not a pointer
}
};
<div class="se-preview-section-delimiter"></div>
Conversion Operators Can Yield Surprising Results
int i = 42;
cin << i; // legal if the conversion to bool were not explicit!
<div class="se-preview-section-delimiter"></div>
<<
defined for istream, but it could use the bool conversion operator to convert cin to bool. The resulting bool value would then be promoted to int and used as the left-hand operand to the built-in version of the left-shift operator. The promoted bool value(1/0) would be shifted left 42 positions.explicit Conversion Operators
class SmallInt
{
public:
// the compiler won't automatically apply this conversion
explicit operator int() const
{
return val;
}
// other members as before
};
<div class="se-preview-section-delimiter"></div>
SmallInt si = 3; // ok: the SmallInt constructor is not explicit
si + 3; // error: operator int is explicit
static_cast<int>(si) + 3; // ok: explicitly request the conversion
<div class="se-preview-section-delimiter"></div>
Conversion to bool
while(std::cin >> value);
Write conversion operators to convert a Sales_data to string and to double. What values do you think these operators should return?
explicit operator string() const
{
return bookNo;
}
explicit operator double() const
{
return avg_price();
}
<div class="se-preview-section-delimiter"></div>
Explain whether defining these Sales_data conversion operators is a good idea and whether they should be explicit.
Explain the difference between these two conversion operators:
struct Integral
{
operator const int();
operator int() const;
};
<div class="se-preview-section-delimiter"></div>
Determine whether the class you used in exercise 7.40 from 7.5.1(p. 291) should have a conversion to bool. If so, explain why, and explain whether the operator should be explicit. If not, explain why not.
Regardless of whether it is a good idea to do so, define a conversion to bool for the class from the previous exercise.
Argument Matching and Mutual Conversions
// a bad idea to have mutual conversions between two class types
struct B;
struct A
{
A() = default;
A(const B&); // converts a B to an A
// other members
};
struct B
{
operator A() const; // also converts a B to an A
// other members
};
A f(const A&);
B b;
A a = f(b); // error ambiguous: f(B::operator A()) or f(A::A(const B&))
<div class="se-preview-section-delimiter"></div>
A a1 = f(b.operator A()); // ok: use B's conversion operator
A a2 = f(A(b)); // ok: use A's constructor
<div class="se-preview-section-delimiter"></div>
Ambiguities and Multiple Conversions to Built-in Types
struct A
{
A(int = 0); // bad idea to have two conversions from arithmetic types
A(double);
operator int() const; // bad idea to have two conversions to arithmetic types
operator double() const;
// other members
};
void f2(long double);
A a;
f2(a); // error ambiguous: f(A::operator int()) or f(A::operator double())
long lg;
A a2(lg); // error ambiguous: A::A(int) or A::A(double)
<div class="se-preview-section-delimiter"></div>
short s = 42;
// promoting short to int is better than converting short to double
A a3(s); // uses A::A(int)
<div class="se-preview-section-delimiter"></div>
Caution: Conversions and Operators
Overloaded Functions and Converting Constructors
struct C
{
C(int);
// other members
};
struct D
{
D(int);
// other members
};
void manipulate(const C&);
void manipulate(const D&);
manipulate(10); // error ambiguous: manipulate(C(10)) or manipulate(D(10))
<div class="se-preview-section-delimiter"></div>
manipulate(C(10)); // ok: calls manipulate(const C&)
<div class="se-preview-section-delimiter"></div>
Overloaded Functions and User-Defined Conversion
struct E
{
E(double);
// other members
};
void manip2(const C&);
void manip2(const E&);
// error ambiguous: two different user-defined conversions could be used
manip2(10); // manip2(C(10) or manip2(E(double(10)))
<div class="se-preview-section-delimiter"></div>
Show the possible class-type conversion sequences for the initializations of ex1 and ex2. Explain whether the initializations are legal or not.
struct Long_Double
{
Long_Double(double = 0.0);
operator double();
operator float();
};
Long_Double Obj;
int ex1 = Obj;
float ex2 = Obj;
<div class="se-preview-section-delimiter"></div>
<div class="se-preview-section-delimiter"></div>
#include <iostream>
using namespace std;
struct Long_Double
{
Long_Double(double = 0.0)
{
cout << "Constructor\n";
}
operator double()
{
cout << "double\n";
return 1.2;
}
operator float()
{
cout << "float\n";
return 1.2;
}
};
int main()
{
Long_Double Obj;
int ex1 = Obj; // error: conversion from ‘Long_Double’ to ‘int’ is ambiguous
float ex2 = Obj; // ok: use `operator float()`
return 0;
}
<div class="se-preview-section-delimiter"></div>
Show the conversion sequences(if any) needed to call each version of calc and explain why the best viable function is selected.
void calc(int);
void calc(Long_Double);
double dval;
calc(dval); // which calc?
<div class="se-preview-section-delimiter"></div>
void calc(int);
: cause class-type conversion is the lowest ranked. a op b
might bea.operator_op(b); // a has operator op as a member function
operator_op(a, b); // operator_op is an ordinary function
<div class="se-preview-section-delimiter"></div>
class SmallInt
{
friend SmallInt operator+(const SmallInt&, const SmallInt&);
public:
SmallInt(int = 0); // conversion from int
operator int() const
{
return val; // conversion to int
}
private:
std::size_t val;
};
<div class="se-preview-section-delimiter"></div>
SmallInt s1, s2;
SmallInt s3 = s1 + s2; // uses overloaded operator+
int i = s3 + 0; // error: ambiguous
<div class="se-preview-section-delimiter"></div>
Which operator+, if any, is selected for each of the addition expressions? List the candidate functions, the viable functions, and the type conversions on the arguments for each viable function:
struct LongDouble
{
// member operator+ for illustration purposes; + is usually a nonmember
LongDouble operator+(const SmallInt&); // 1
// other members as in § 14.9.2 (p. 587)
};
LongDouble operator+(LongDouble&, double); // 2
SmallInt si;
LongDouble ld;
ld = si + ld;
ld = ld + si;
<div class="se-preview-section-delimiter"></div>
ld = si + ld;
is ambiguous.ld = ld + si
can use both 1 and 2, but 1 is more exactly. For 2, SmallInt need to convert to double.Given the definition of SmallInt on page 588, determine whether the following addition expression is legal. If so, what addition operator is used? If not, how might you change the code to make it legal?
SmallInt s1;
double d = s1 + 3.14;
<div class="se-preview-section-delimiter"></div>
SmallInt s1;
double d = s1 + SmallInt(3.14);
Chapter Summary
Please indicate the source: http://blog.csdn.net/gaoxiangnumber1
Welcome to my github: https://github.com/gaoxiangnumber1