可能算是心血来潮吧,想着把自己学的东西每天总结总结,权当是一个复习,同样也能当一个挺好的回忆吧,这个阶段马上就要准备期末考试了,所以可能会断更一段时间,虽然是心血来潮,还是希望自己能坚持下来,觉得每天写博客还是能带来不少提升的。
C++ Primer
1.委托构造函数
这个知识点很简单,总结下来只有一句话,让它所属类的其他构造函数执行它自己的初始化过程
举个例子
class Sales_data {
public:
//构造函数的初始化列表基本都是借助第一个构造函数来实现的
Sales_data(string s, unsigned cnt, double price) :
bookNo(s), units_sold(cnt), revence(cnt* price) {
}
Sales_data() : Sales_data("", 0, 0) {}
Sales_data(string s) : Sales_data(s, 0, 0) {}
Sales_data(istream& is) : Sales_data() { read(is, *this); }
//上面这个构造函数进行了多重为委托,把自己委托给了默认构造函数,默认构造函数委托给了第一个有参构造函数
};
2.默认构造函数
这个函数是编译器自己提供的构造函数,没有什么说的,是一个很细小的知识点(主要是之前学过,这里只是提一下一种新的书写方式)
如果我们需要显示的写一下默认构造函数,现在有一种新的写法,不需要再从头到尾自己实现一遍
class String{
String() = default;
//可直接写成如上形式,唯一需要注意的点是,这样写的默认构造函数需要加小括号。
}
3.转换构造函数
如果构造函数只接受一个实参,则它实际上定义了转换为此类型的隐式转换机制,有时我们把这种构造函数称为转换构造函数
简单说,转换构造函数能通过一个实参调用的构造函数定义了一条从构造函数的参数类型向类类型隐式转换的规则
string null_book = "9-999-99999-9";
item.combine(null_book);
//通过借助一个只接受一个string类型参数的构造函数,隐式的将一个string类型的参数转换成了类类型参数
//值得注意的是,编译器只会自动的执行一步类型转换
4.抑制构造函数定义的隐式转换
我们可以通过加上explicit关键字抑制类的隐式转换
这个关键字只对一个实参的构造函数有效,只能在类内声明构造函数的时候使用explicit关键字,在类外部定义时不应该重复。
explicit构造函数只能用于直接初始化
Sales_data item1(null_book);
Sales_data items = null_book;
//如果构造函数不加explicit关键字,上述的两种创建对象的方式都是可以的
//如果加了关键字,就只能用第一种方式,不能采用复制初始化。
5.聚合类
聚合类使得用户可以直接访问其成员(说白了就是c语言里的struct,不过还是有差距),聚合类是有特殊的初始化语法的(初始化列表),当满足以下条件时,我们说它是聚合的。
1.所有成员都是public
2.没有定义任何构造函数
3.没有类内初始值
4.没有基类,没有virtual函数
对于第三点,在VS2019上实操的时候好像并没有报错。
我们可以利用初始化列表初始化聚合类,但要按照声明的顺序进行初始化。
6.字面值常量类
数据成员都是字面值类型的聚合类时字面值常量类,如果一个类不是聚合类,但符合下述要求,那它也是一个字面值常量类:
1.数据成员都必须是字面值类型
2.类必须至少含有一个constexpr构造函数
3.如果一个数据成员含有类内初始值,则内置类型成员额初始值必须是一条常量表达式,或者如果成员属于某种类类型,则初始值必须使用成员自己的constexpr构造函数
4.类必须使用析构的默认定义,该成员负责销毁类的对象
个人目前感觉这个知识点并不经常用到,所以就不举实例了,以后用到了再说。
7.类的静态成员
静态数据成员的类型可以是常量,引用,指针,类类型等。
静态成员函数也不与任何对象绑定在一起,它们不包含this指针,作为结果,静态成员函数不能声明成const的,我们也不能在static函数体内使用this指针。
我们可以直接使用作用域运算符直接访问静态成员。也可以使用类的对象,引用或指针访问静态成员。
成员函数不需要通过作用域运算符就能直接使用静态成员。
定义静态成员
静态成员一般都是类内声明,类外定义,当在类外定义静态成员时,不能重复static关键字,该关键字只出现在类内部的声明语句。
类内声明的静态变量在类外定义的时候,是可以访问到类内的私有变量的。
静态变量的初始化自然也有特殊情况,也是可以在类内初始化的。
要在类内初始化静态变量,要求静态变量必须是constexpr,譬如以下这种形式
static constexpr int period = 30;
如果在类内初始化了静态变量,最好在类外再定义一遍这个静态变量,但不需要指定初始值。
静态成员能用于某些场景,而普通成员不行
静态成员和指针成员可以是不完全类型,数据成员必须是完全类型
不完全类型
类只有声明没有定义完全的时候就是一个不完全类型
8.IO类
IO对象无拷贝或者赋值
我们不能拷贝或对IO对象赋值,所以重载时作为返回值或参数的时候都得用引用
如果IO流一旦接受了不与目标参数一致的参数的时候,就会失效,这个时候可通过cin.clear()恢复输入流。
侯捷
学到了转换函数
主要是用来转换类型的,假设我们定义了一个分数类,可通过转换函数,将这个类转换成double类型的数字,即可直接进行转换。代码如下
#include<iostream>
using namespace std;
class Fraction {
public:
Fraction(int num, int den = 1)
: m_numerator(num), m_denominator(den) {}
//cpp转换函数,转换类型,
//如果需要把Fraction转换成double的时候,就来调用下面这个函数
//转换函数是不需要写返回值的
operator double() const {
return static_cast<double> (m_numerator * 1.0 / m_denominator);
}
private:
int m_numerator;//分子
int m_denominator;//分母
};
int main() {
Fraction f(3, 5);
double d = 4 + f;
cout << d << endl;
return 0;
}