//professional c++ 4th edition p 331
#include
class FunctionObject{
public:
int operator() (int param);
int doSquare (int param);
};
int FunctionObject::operator() (int param){
return doSquare(param);
}
int FunctionObject::doSquare(int param){
return param * param;
}
int main(){
int x = 3, xSquared, xSquaredAgain;
FunctionObject square;
xSquared = square(x);
xSquaredAgain = square.doSquare(x);
}
//professional c++ 4th edition p332
#include
#include
#include
#include
#include
#include <string_view>
#include
#include
using namespace std::rel_ops;
class SpreadsheetCell{
public:
SpreadsheetCell() = default;
SpreadsheetCell(double initialValue);
explicit SpreadsheetCell(std::string_view initialValue);
void set(double inValue);
void set(std::string_view inString);
double getValue() const { mNumAccesses++; return mValue; }
std::string getString() const { mNumAccesses++; return doubleToString(mValue); }
static std::string doubleToString(double inValue);
static double stringToDouble(std::string_view inString);
SpreadsheetCell& operator+=(const SpreadsheetCell& rhs);
SpreadsheetCell& operator-=(const SpreadsheetCell& rhs);
SpreadsheetCell& operator*=(const SpreadsheetCell& rhs);
SpreadsheetCell& operator/=(const SpreadsheetCell& rhs);
//p325
SpreadsheetCell operator-() const;
SpreadsheetCell& operator++(); // prefix
SpreadsheetCell operator++(int); // postfix
SpreadsheetCell& operator--(); // prefix
SpreadsheetCell operator--(int); // postfix
//p335
//operator double() const; // 问题出在这!
operator std::string() const;
/*p497
The usual pre-C++11 solution to this conundrum is to make the constructor in question explicit, so that
the automatic conversion using that constructor is prevented(see Chapter 9). However, you don’t want
that constructor to be explicit because you generally like the automatic conversion of doubles to
SpreadsheetCells. Since C++11, you can solve this problem by making the double conversion operator explicit
instead of the constructor: //
explicit operator double() const; // 此处与上行 矛盾
private:
double mValue = 0;
mutable size_t mNumAccesses = 0;
};
//p327
std::ostream& operator<<(std::ostream& ostr, const SpreadsheetCell& cell);
std::istream& operator>>(std::istream& istr, SpreadsheetCell& cell);
//p336
bool operator==(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs);
bool operator<(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs);
bool operator>(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs);
bool operator!=(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs);
bool operator<=(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs);
bool operator>=(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs);
-
SpreadsheetCell::SpreadsheetCell(double initialValue)
-
mValue(initialValue){
}
SpreadsheetCell::SpreadsheetCell(std::string_view initialValue)
-
mValue(stringToDouble (initialValue)){
}
void SpreadsheetCell::set(double inValue)
{
mValue = inValue;
}
void SpreadsheetCell::set(std::string_view inString){
mValue = stringToDouble(inString);
}
std::string SpreadsheetCell::doubleToString(double inValue){
return std::__cxx11::to_string(inValue);
}
double SpreadsheetCell::stringToDouble(std::string_view inString){
return strtod(inString.data(), nullptr);
}
SpreadsheetCell operator+(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs){
return SpreadsheetCell(lhs.getValue() + rhs.getValue());
}
SpreadsheetCell operator-(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs){
return SpreadsheetCell(lhs.getValue() - rhs.getValue());
}
SpreadsheetCell operator*(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs){
return SpreadsheetCell(lhs.getValue() * rhs.getValue());
}
SpreadsheetCell operator/(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs){
if(rhs.getValue() == 0){
throw std::invalid_argument(“Divide by zero.”);
}
return SpreadsheetCell(lhs.getValue() / rhs.getValue());
}
SpreadsheetCell& SpreadsheetCell::operator+=(const SpreadsheetCell& rhs){
set(getValue() + rhs.getValue());
return *this;
}
SpreadsheetCell& SpreadsheetCell::operator-=(const SpreadsheetCell& rhs){
set(getValue() - rhs.getValue());
return *this;
}
SpreadsheetCell& SpreadsheetCell::operator*=(const SpreadsheetCell& rhs){
set(getValue() * rhs.getValue());
return *this;
}
SpreadsheetCell& SpreadsheetCell::operator/=(const SpreadsheetCell& rhs){
if (rhs.getValue() == 0) {
throw std::invalid_argument(“Divide by zero.”);
}
set(getValue() / rhs.getValue());
return *this;
}
bool operator==(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs){
return (lhs.getValue() == rhs.getValue());
}
bool operator<(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs){
return (lhs.getValue() < rhs.getValue());
}
//p325
SpreadsheetCell SpreadsheetCell::operator-() const
{
return SpreadsheetCell(-getValue());
}
SpreadsheetCell& SpreadsheetCell::operator++()
{
set(getValue() + 1);
return *this;
}
SpreadsheetCell SpreadsheetCell::operator++(int)
{
auto oldCell(*this); // Save current value
++(*this); // Increment using prefix ++
return oldCell; // Return the old value
}
SpreadsheetCell& SpreadsheetCell::operator–()
{
set(getValue() - 1);
return *this;
}
SpreadsheetCell SpreadsheetCell::operator–(int)
{
auto oldCell(*this); // Save current value
–(*this); // Decrement using prefix –
return oldCell; // Return the old value
}
//p328
std::ostream& operator<<(std::ostream& ostr, const SpreadsheetCell& cell)
{
ostr << cell.getValue();
return ostr;
}
std::istream& operator>>(std::istream& istr, SpreadsheetCell& cell)
{
double value;
istr >> value;
cell.set(value);
return istr;
}
//p334
SpreadsheetCell::operator double() const{ //(1)
return getValue();
}
SpreadsheetCell::operator std::string() const{ //(1)
return doubleToString(getValue());
}
//p336
bool operator>(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
return (lhs.getValue() > rhs.getValue());
}
bool operator!=(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
return (lhs.getValue() != rhs.getValue());
}
bool operator<=(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
return (lhs.getValue() <= rhs.getValue());
}
bool operator>=(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
return (lhs.getValue() >= rhs.getValue());
}
template class Pointer{
public:
Pointer(T* ptr);
virtual ~Pointer();
Pointer(const Pointer& src) = delete;
Pointer& operator = (const Pointer& rhs) = delete;
//p333
T& operator*();
const T& operator*() const;
T* operator->();
const T* operator->() const;
//p336
operator void* () const;
//operator bool () const;
private:
T* mPtr = nullptr; // mPtr 打错了 mptr
};
template Pointer::Pointer(T* ptr) : mPtr(ptr){
}
template Pointer::~Pointer(){
delete mPtr;
mPtr = nullptr;
}
template T& Pointer::operator*()
{
return *mPtr;
}
template const T& Pointer::operator*() const
{
return *mPtr;
}
template T* Pointer::operator->()
{
return mPtr;
}
template const T* Pointer::operator->() const
{
return mPtr;
}
void testConst(const Pointer& p)
{
std::cout << *p;
// *p = 7;
}
void TestConstTwo(const Pointer& p)
{
// p->set(5);
}
//p336
template Pointer::operator void* () const
{
return mPtr;
}
//template Pointer::operator bool () const
//{
// return mPtr != nullptr;
//}
void process(Pointer& p){
if(p != nullptr) {std::cout << “not nullptr” << std::endl;}
if(p != NULL) {std::cout << “not NULL” << std::endl;}
if§ {std::cout << “not NULL” << std::endl;}
if(!p) {std::cout << “nullptr” << std::endl;}
}
int main(){//p333
Pointer smartInt(new int);
*smartInt = 5;
std::cout << *smartInt << std::endl;
Pointer<SpreadsheetCell> smartCell1 (new SpreadsheetCell);
smartCell1->set(5);
std::cout << smartCell1->getValue() << std::endl;
//p334
SpreadsheetCell myCell1;
double (SpreadsheetCell::*methodPtr) () const = &SpreadsheetCell::getValue;
std::cout << (myCell1.*methodPtr)() << std::endl;
SpreadsheetCell* myCell2 = new SpreadsheetCell();
std::cout << (myCell2->*methodPtr)() << std::endl;
SpreadsheetCell cell1(1.23); //(1)
//double d1 = cell1; // operator double() const; Works as expected
//std::string str1 = cell1;
//double d2 = cell1 + 3.3; //Do not complie if you define operator double()
//p335
SpreadsheetCell cell3 (6.6); //[1]
std::string str2 = cell3; //[2]
double d3 = static_cast<double>(cell3); //[3]
double d4 = static_cast<double>(cell3 + 3.3); //[4]
std::cout << str2 << std::endl;
std::cout << d3 << std::endl;
std::cout << d4 << std::endl;
/*p497
//[1]Uses the implicit conversion from a double to a SpreadsheetCell. Because this is in the declaration,
this is done by calling the constructor that accepts a double.
//[2]Uses the operator string() conversion operator.
//[3]Uses the operator double() conversion operator. Note that because this conversion operator is now
declared explicit, the cast is required.
//[4]Uses the implicit conversion of 3.3 to a SpreadsheetCell, followed by operator+ on two SpreadsheetCells
, followed by a required explicit cast to invoke operator double().
Pointer<SpreadsheetCell> smartCell2(nullptr);
process(smartCell2);
std::cout << std::endl;
Pointer<SpreadsheetCell> anotherSmartCell(new SpreadsheetCell(5.0));
process(anotherSmartCell);
return 0;
}
/*
wannian07@wannian07-PC:~$ g++ -std=c++17 -o c17 c17.cpp
wannian07@wannian07-PC:~$ ./c17
5
5
0
0
6.600000
6.6
9.9
nullptr
not nullptr
not NULL
not NULL
*/