内联函数及内联函数的好处
以inline修饰的函数就叫做内联函数,C++编译器在编译时会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序的运行效率。规模较小而又被频繁调用的简单函数,才适合定义为inline函数。
内联函数在调用时不是像一般函数那样要转去执行被调用的函数体,执行完后再转回调用函数中,执行其后的语句;而是在调用处用内联函数体的代码来替换,以这样的方式节省函数调用的开销,提高运行效率。节约时间,浪费空间。
类中成员函数怎么变成内联函数
在类中直接实现,在类的内部定义成员函数,这样的成员函数会隐式地被声明为内联函数。
class Box {
public:
int length;
int width;
int height;
int getVolume(void) //内联函数
{
return length * width*height;
}
};
在类的声明外部定义成员函数,但是在定义时使用inline关键字,这样成员函数会显式地被声明为内联函数。
class Box {
public:
int length;
int width;
int height;
int getVolume(void); //声明
};
inline int Box::getVolume(void) //内联函数
{
return length * width*height;
}
宏和内联函数的区别
宏只是单纯的字符串拷贝,在预处理阶段进行文本替换,内联函数是在编译阶段进行代码展开。
宏没有类型检查,不安全,而内联函数是真正的韩束,只在需要用到的时候内联函数像宏一样展开,所以取消了函数的参数压栈,减少了调用的开销。
const
修饰变量,说明该变量不可以被改变
修饰指针,分为指向常量的指针(const int *)和自身是常量的指针(int * const)
修饰引用,指向常量的引用,用于形参类型,即避免了拷贝,又避免了函数对值得修改
修饰成员函数,说明该成员函数内不能修改成员变量
常函数参数可以被改变,可以在常函数中修改成员变量,类中常函数和非常函数也可以修改
重写
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 函数名、返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
在子类中可以根据需要对从基类中继承来的方法进行重写,重写是对类中方法的扩充,因为继承用的是父类的东西,重写则不仅得到父类的东西,同时也加入了自己的东西
多态实现的原理
用父类指针指向子类对象,然后通过父类的指针/引用 调用实际子类的成员函数。实现多态有两种方式:静态多态和动态多态。静态多态主要是重载和模板,在编译时确定;动态多态用虚函数机制实现(重写),在运行期间动态绑定。
虚函数的实现:在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中放了虚函数的地址,实际的虚函数在代码段(.text)中。当子类继承了父类的时候也会继承其虚函数表,当子类重写父类中虚函数时候,会将其继承到的虚函数表中的地址替换为重新写的函数地址。使用了虚函数,会增加访问内存开销,降低效率。
函数隐藏,重写,重载的区别
重载:是指同一可访问区内被声明几个具有不同参数列(参数的类型、个数、顺序)的同名函数,根据参数列表确定调用哪个函数,重载不关心函数返回类型。
隐藏:在父类和子类中只要函数名相同就构成函数隐藏(不要求函数返回值和函数参数类型相同)。具体执行父类函数还是子类函数看哪个类型的之后怎调用的这个函数。比如派生类成员函数屏蔽与其同名的基类成员函数、类成员函数屏蔽全局外部函数。请注意,如果在派生类中存在与基类虚函数同返回值、同名且同形参的函数,则构成函数重写。
重写:是指派生类中存在重新定义的函数。函数名、参数列表、返回值类型都必须同基类中被重写的函数一致,只有函数体不同。派生类调用时会调用派生类的重写函数,不会调用被重写函数。重写的基类中被重写的函数必须有 virtual 修饰。
多继承问题
多继承指的是一个子类可以同时继承多个父类,从而具备多个父类的特征。
菱形继承:

会导致D中有两份A的数据,多数情况这都是多余的,并且可能导致二义性错误。
可以用作用域解决二义性问题
可以用虚继承解决二义性问题,使得不同路径继承来的同名成员在内存中只有一份拷贝。