类中的this
指针
在类中this
是一个隐式参数,指向调用他的那个对象。因为this
的目的是指向对象,所以this
是一个常量指针,不能修改this
中保存的地址。
在默认情况下,this
是一个指向非常量的常量指针。例如类是sale_data
,this
指针的类型为sale_data *const
。之前书上提到过,常量指针是不能绑定常量对象上的。例如:
1 | int p1 = 1; |
所以如果想函数内部不改变对象的内容,则在函数后面加上const
。例如:1
2
3
4string isbn() const
{
return bookNo;
}
c++11新标准-默认构造函数default
当我们的类需要一个默认的构造函数时,我们可以使用如下的句式为类sale_data
要求一个编译器自动生成的构造函数。1
Sales_data() = default;
如果上述句式出现在类内,默认构造函数是内联的。如果出现在类外,则不是内联的。
定义类 - class
和struct
使用class
和struct
定义类的唯一区别就是默认访问权限不同。class
默认是private
,struct
默认是public
。
可变数据成员 - mutable
如果在某种情况下,你希望即使在一个const函数内,也要修改某个数据成员,你就在这个数据成员的声明前加上mutable
关键字。1
2
3
4
5
6
7
8
9
10class Screen {
public:
void some_member() const;
private:
mutable size_t access_ctr;
};
void Screen::some_member() const
{
++access_ctr;
}
上述例子中,即使some_member
函数是一个const函数,我们也可以修改access_ctr
的值。
返回*this
的成员函数
1 | class Screen { |
根据上述例子,set
函数返回的是调用set的对象的引用,这样我们可以将一系列操作链接成一句表达式。1
myScreen.set('1').set('2')
我们可以看到这个表达式等价于:1
2myScreen.set('1');
myScreen.set('2');
如果返回的是screen而不是screen&,我们只能在*this上的拷贝副本进行set('2')
,等价于:1
2Screen temp = myScreen.set('1');
temp.set('2');
而此时如果使用的是display
函数,由于它是常量函数,所以返回的应该是const Screen&
,这时候下面的句子会出现问题。1
myScreen.display().set('2')
因为此时display
返回的是常量引用,而set
无权对此操作。
## 友元
- 友元类可以访问该类中的非公有成员,只需要在友元类声明的前面加上
friend
。 - 友元关系没有传递性,友元类的友元类不能也可以访问该类中的非公有成员。
## 成员初始化的顺序
成员的初始化顺序与他们在类定义中的出现顺序一致,而与在构造函数的初始化列表顺序无关。
聚合类和字面值常量类
聚合类有如下特征:
- 所有成员都是public的。
- 没有定义任何构造函数。
- 没有类内初始值
- 没有基类没,没有
virtual
函数。
字面值常量类
- 数据成员全是字面值类型。
- 至少含有一个
constexpr
构造函数。 - 类必须使用析构函数的默认定义。
- 如果一个数据成员含有类内初始值,则初始值必须是一条常量表达式。如果成员属于某种类类型,则初始值必须使用成员自己的constexpr构造函数。
静态static
成员
- 静态成员不与任何对象绑定在一起,它属于整个类。
- 静态成员不包含
this
指针。 - 静态成员不能声明成
const
的。 - 不能在静态函数内使用this指针。
- 静态成员必须在类的外部定义和初始化。
静态成员与非静态的一些试用场景区别:
- 静态成员可以被类函数当做默认实参,而非静态成员不可以。因为非静态成员的值本身就属于对象的一部分。
- 静态成员的类型可以是他所属类的类型,但是非静态成员不可以。