【C++】02-C++面向对象高级编程(下)-笔记(侯捷系列)

1、当一个类需要转换成其他类型(任何一种前面已经定义过的类型,不一定是内置类型)时,需要使用转换函数。

例如一个类如果要转换为double,则需定义函数:

operator double() const 
{ 
    // ... 
    return (double)(...);
}

2、加了explicit修饰符的构造函数是不允许隐式转换的。

当构造函数只有一个实参(它可以有两个以上的形参,但是由于有默认实参,当构造该对象时,只要传入一个参数,就可以构造出该对象),就有可能在某种场景下出现隐式转换。

3、为避免同名的函数产生冲突,最好是用namespace把函数包起来。

4、成员模板可以用于模板构造函数的拷贝构造函数(一般是用于继承)。所以说泛型编程其实是兼容继承的。

5、模板主要是分成三大类:类模板、函数模板、成员模板。

6、模板特化:对于一些特别的类型要做特别的处理。与特化相对的是泛化。

7、模板偏特化:个数的偏(例如指定typename为某一种类型)和范围的偏(例如指定typename为指针类型)。

8、学习标准库最好的方法是用小工具全部测一遍它们。

9、打印 C++ 当前的版本,以确定当前编译器是否支持 C++11。

cout << _cplusplus << endl;

10、C++11支持数量不定的模板参数.

void print()
{

}

template<typename T, typename... Types>
void print(const T& firstArg, const Type&... args)
{	
	cout << firstArg << endl;
	print(args...);    // args为0个参数时,调用上面那个形参为空的函数
}

sizeof...(args); // 可以知道参数包的个数

11、使用auto关键字的时候,一定是要能让编译器能推断出该类型。

12、范围循环。

vector<double> vec;
...
for(auto elem : vec)		// 值传递
{
	cout << elem << endl;
}
for(auto& elem : vec)		// 引用传递
{
	elem *= 3;
}

13、foreach循环。

std::for_each(stdMap.cbegin(), stdMap.cend(), [](auto& item) // C++14在lambda支持auto
{
	qDebug() << item; // 逐行输出std::pair(1,10) std::pair(2,20) std::pair(3,30)
});

14、编译器就是以指针的角度去看待引用的。

  • 32位编译器,指针是4个字节大小。
  • 引用一定要有初值,告诉编译器它要代表谁。
  • 设置r之后,r不能再重新代表其他变量。
  • Java里面所有的变量都是引用。
  • 引用通常不用于声明变量,而用于参数传递和返回值。
qint64 nCnt = 10;
qint64* p = &nCnt;
qint64& r = nCnt;

qDebug() << nCnt;	// 10
qDebug() << &nCnt;	// 0x69fdb8
qDebug() << p;		// 0x69fdb8
qDebug() << &r;		// 0x69fdb8
qDebug() << sizeof nCnt;	// 8
qDebug() << sizeof p;		// 4
qDebug() << sizeof r;		// 8---r代表nCnt

15、函数签名一样,下面二个函数不能同时存在。

int calCnt(const int& nCnt) { ... }
int calCnt(const int nCnt) { ... }
函数签名不包含函数的返回类型。
函数重载不考虑函数的返回类型。
注意,const是函数签名的一部分。

16、析构的顺序与构造的顺序相反。

17、当类含有一个或多个虚函数,该对象在内存中就会存在一个虚指针。

  • 类的父类有虚函数,子类也会有虚函数,也就有虚指针。
  • 所谓继承是继承函数的调用权,不是函数的内存大小。

18、虚指针指向虚表。

  • 虚表存放函数指针,指向虚函数所在的位置。
  • 如果子类重写了父类的虚函数func,则子类对象的虚表中不再含有父类虚函数func的指针。

19、动态绑定的意义在于 通过类new的指针p找到虚指针,然后通过虚指针找到虚表,然后在虚表中看看找到哪个函数。

(*(p->vptr)[n])(p);		// 后面的参数(p)的意思是传递this指针
或
(* p->vptr[n] )(p);

20、this就是调用函数的那个对象的地址。

21、通过对象调用,就是静态绑定。

B b;
A a = (A)b;
a.vFunc();		//  这样是调用父类A的虚函数vFunc

22、当一个函数要加const(这个函数不打算改变class的data)却没有加const的时候,一个const对象调用该函数就会有问题(常量对象不能调用非常量成员函数)。

int getCnt() const { return nCnt; }
const只能放在成员函数的后面,不能放在全局函数的后面。

23、当成员函数的const和non-const版本同时存在,const对象只会调用const版本,non-const对象只会调用non-const版本。

24、::new是强制调用全局的意思。::是全局范围操作符。

全局函数也是可以重载的。

25、 如果一个没有虚函数的类A的大小是12字节,则它有虚函数的时候,类A的大小是16字节。

  • 如果一个类A的大小是12字节,则
  • new A();就是12字节,而new A[5];则是12*5+4=64字节,其中多出来的那4个字节存放变量5.
  • 类似的,如果一个有虚函数的类A,new A[5];的大小是16*5+4=84字节。

26、new的另一用法。举个例子,可以使用new(extra) 扩充内存申请量。

size_t extra;
Rep* p = new(extra) Rep;

void* operator new(size_t s, size_t extra)
{
	return Allocator::allocate(s+extra*sizeof(charT));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值