一、初始化列表:它的顺序应该和声明顺序一致,否则会引起初始化错误
class A{
private:
const int a;
double b;
char c;
public:
A(int a_, double b_, char c_) : a(a_), b(b_), c(c_){}
};
在对类对象做赋值时,调用的拷贝构造函数,赋值调用的赋值重载
class B{
private:
A obj_A;
int b;
public:
//使用初始化列表的形式
B(A a, int b_) : A(obj_A), b(b_){}
//使用正常构造方法的形式
B(A a, int b_){
this ->a = a;
b = b_;
}
};
(1).在初始化列表进行初始化操作时,首先const成员和引用必须在初始化列表中进行初始化
(2).而缺省默认构造函数的类对象也必须在初始化列表中进行初始化,因为在构造函数中会先调用该类的默认构造函数
(3).对于有默认构造函数的类,初始化列表会调用赋值重载函数:operator=(),赋值重载函数会调用拷贝构造函数
而在构造函数中,会先调用默认构造函数,在调用赋值重载函数:operator=(),最后调用拷贝构造函数
因此初始化列表对于有默认构造函数的类对象会有更高的效率。
调用拷贝构造函数的三种情况,1.该对象作为参数时,2.该对象作为返回值时,3.初始化别的对象时。
二、空类
C++在底层实现时会保留一个字节,因为不能让对象不占内存。
由于现在的系统都是按字节编址,因为保留一个字节作为空类的对象。但字节里没有特定值。
编译器会自动默认生成的函数:
1.default constructor
2.default distructor
3.copy constructor
4.operator=()
5.operator&()
6.operator&()const
这几个函数虽然会默认生成,但是并不是说,肯定会生成它们
要是用不到,就不会生成
三、虚拟继承的实现
假设有以下继承体系
class Top{
private :
int a;
};
class Left : public Top{
private :
int b;
};
class Right public Top{
private :
int c;
}
class Bottom : public Left, public Right{
private :
int d;
};
//创建Bottom对象
Bottom * ptr_Bottom = new Bottom();
那么在这个Bottom对象中的内存布局如下
Left::Top::a Left::b Right::Top::a Right::c Bottom::d
我们如果执行: Left * ptr_Left = ptr_Bottom;
操作是正常的,因为Bottom对象中首先继承left,因此left对象就在前面
而如果我们执行: Right * ptr_Right = ptr_Bottom;
四、this指针
C++对象模型中,成员函数是不在对象的内存中的,对象的内存中只存放虚函数表、成员变量
在调用成员函数时,怎么知道调用的哪个对象的成员函数,这一点是由this指针保证的
在成员函数的第一个参数,会默认有一个形参名为this的指针参数
哪个对象调用该成员函数,它的值就是谁的地址值
所以可以通过this->data来访问该对象的数据成员
而*this则表示该对象
所以说,对于this指针一个类只有一份
因为函数只有一份
const 用法:
1.const修饰普通变量,表示该变量为常变量,不能被修改
2.cosnt修饰指针,会优先修饰数据类型,否则才会修饰*
int const * a;表示a指向的是常量
const int * a;表示a指向的是常量
int * const a;表示a是一个常量指针,所指的对象不能被修改
3.const修饰引用,与修饰指针相同
4.const修饰函数:void fun()const;其实等价于:void fun(const className * this);
const修饰函数的功能是通过作用在this指针上完成的。因此const只能修饰成员函数,不能修饰static函数或普通函数
五、多态
多态分为编译时多态(重载)和运行时多态(多态)
1.函数重载: 由于C++对函数处理比较特殊,如void fun(int a, char b) 转换成fun_int_char这种形式,所以不同的参数类型和各种就可以形成不同的函数
这也是重载的定义,函数名称相同,函数的参数个数和参数类型不同,注意此处不要求返回值
多个重载的函数,实际形成的函数名会根据参数列表的不同而划分,是不是在编译的时候,调用不同的函数,调用时就会函数列表进行对比最终匹配到参数列表相同的函数
2.函数多态
对于含有虚函数的类,它的实例化对象中会有一个虚函数指针,该指针指向虚函数表。
函数会被放在符号表里
通过查符号表知道调用哪个函数,这都是编译过程完成的
虚函数,虚函数表类似于符号表,不过它存的是虚函数的地址
然后,调用哪个虚函数和符号表一样,都是查表的过程
所以,虚函数的引入其实是会拖慢效率的
父类的相同函数被定义为虚函数,该类的派生类的相同函数自动被虚化,无论有没有加virtual关键字,但是一般习惯是给子类加上virtual,为了阅读方便
而虚函数表一般都被放置于对象的头4个字节