7.47--要看用户的需求,如果需要使用到这种隐性的类型转换,则可以这样,但是如果用了explict关键字的话,如果用到这种转换,就要去显示的使用类型转换。所以还是要看用不用得到这种类型转换。
7.48
string null_isbn("99-999-99999-9");//定义了一个值为99-999-99999-9的string变量null_isbn
Sales_date item1(null_isbn);//隐式的类型转换,将string变量null_isbn隐式的转换成Sales_date的对象
Sales_date item2("99-999-99999-9");//错误,不能直接进行两步类型转换,只能一步类型转换
Sales_date item3(string null_isbn("99-999-99999-9"));//正确:一步一步的进行隐式的类型转换
7.49
Sales_date &combine(Sales_date );
i.combine(s);//可以的,一步隐式转换
Sales_date &combine(Sales_date& );
i.combine(s);//不可以,Sales_date&指的是Sales_date的地址,无法将string类型的变量转变成Sales_date&地址
Sales_date &combine(const Sales_date& ) const;
i.combine(s);//不行,combine是要改对象的,const常量对象不能改,不会修改数据成员的函数都要加上const
这里我想普及一个小的知识点,primer前面也讲过了,但是我资质愚钝,现在才明白一些,就是const放在函数声明前面,放在函数声明后面,和放在函数参数前面,有什么区别
1,const放在函数声明前面:放在函数声明最前面就是对返回值类型进行修饰,这里分两种情况,第一种就是按指针传递 那么函数返回值(即指针)的内容不能被修改 例如:
const int * getline();
int *ptr=getline();//错误,getline()的返回值只能被赋给加const修饰的同类型指针
const int * s = getline();//正确,getline()的返回值只能被赋给加const修饰的同类型指针
第二种情况就是按值传递的时候 在函数按值传递时没有什么意义
如果返回值是外部的数据类型,也就是除了基本数据类型之外的类型,比如将函数 xxx Getxxx() 改写为const xxx &Getxxx()能使得程序效率高
2,const放在函数声明后面 这叫const成员函数,例如
int get_number() const; // const 成员函数
任何不希望通过本函数修改成员的函数都应该声明为const函数
const成员函数,不能修改数据成员,不能调用其它非const成员函数,否则编译器将报错
例如
class A{
public :
int get_number()const;
void set_number(int i);
private:
int number;
};
int A:: get_number()const{
set_number(6);//错误,调用了非const函数;
number-=9;//错误,修改了数据成员
}
从思想上去理解,表象就是:const成员函数就是不让修改对象的存储空间,任何当前对象存储空间的修改都会报错
深层次的理解就是 打个比方
class A{
public :
void xxx(string);
};
当我们在使用xxx函数的时候,其实用到了两个东西,一个是A*const this,也就是当前的A对象,另一个是string参数
1,不想改变string参数 就用const 修饰它,void xxx(const string ) ;
2,不想改变指向当前对象,就在函数后面加const 得到void xxx(const string ) cosnt;'
--->编译时编译器就会懂了是要编程const A *const this 两个不能变。。。
3,const 修饰函数参数
按值传递时候无所谓
但是按地址传递时候,外部数据类型 xxx get(xxx a)的效率就要比 xxx get(xxx &a)的效率要低,但是反过来讲,xxx get(xxx &a)方法中游客可能对对象数据进行修改,这时候 加上个const就不会出现不小心修改了对象数据地址内存放的地址信息了
7.52
中这样的初始化方式是有问题的,原本的Sales_date类不能这样进行初始化
要写一个7.5.5节这样的聚合类:
class Sales_date{
std::string bookNo;
unsigned units_sold;
double revence;
};
这样再去用
Sales_date item={"ssssssss",12,15.3};
就没有问题了
7.53,
没什么可说的,书上的代码,理解一下costexpr关键字修饰的函数返回的是常量,修饰构造函数时要求函数体为空
class Debug{
public:
constexpr Debug(bool b=true):hw(b),io(b),other(b){}
constexpr Debug(bool h,bool i,bool o):
hw(h),io(i),other(o){}
constexpr any(){return hw||io||other;}
void set_io(bool b){io =b;}
void set_hw(bool b){hw =b;}
void set_other(bool b){other =b;}
private:
bool hw;//硬件错误
bool io;//io错误
bool other;//其他错误
};
7.54 根据对constexpr关键字的认识,修饰普通成员函数的时候要返回一个常量
所以不能
7.55
不属于
类不属于字面值类型
7.56
7.56 静态成员就是与类相关独立于类的对象之外的成员。
有些操作使用静态成员十分方便。、
普通成员需要进行类的实例化,是对于对象而言的操作,但是静态数据成员是对于类的操作。
7.57
class Account{
public:
void calculate(){
amount += amount * intrestRate;
}
static double rate(){
return intrestRate;
}
static void rate(double);
private:
static constexpr int period = 30;
double daily_tbl[period];
std::string owner;
double amount;
static double intrestRate;
static double initRate();
};
7.58
静态的常量表达式要用constexpr修饰
// example.h
class Example {
public:
static constexpr double rate = 6.5;//加上了constexpr 修饰
static const int vecSize = 20;
static vector vec;//类内不能初始化vector类型的数据成员
};
// example.C
#include "example.h"
constexpr double Example::rate;//一个不带初始值的静态成员的定义
vector Example::vec(Example::vecSize);//类外初始化vector类型的数据成员