https://www.nowcoder.com/tutorial/93/8f38bec08f974de192275e5366d8ae24
● 说一下static关键字的作用
1. 全局静态变量
未经初始化的全局静态变量会被自动初始化为0
全局静态变量在声明他的文件之外是不可见的,准确地说是从定义之处开始,到文件结尾。
2. 局部静态变量
作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。但是当局部静态变量离开作用域后,并没有销毁,而是仍然驻留在内存当中,只不过我们不能再对它进行访问,直到该函数再次被调用,并且值不变;
3. 静态函数
函数的实现使用static修饰,那么这个函数只可在本cpp内使用,不会同其他cpp中的同名函数引起冲突
4. 类的静态成员
静态成员可以实现多个对象之间的数据共享,对多个对象来说,静态数据成员只存储一处,供所有对象共用
5. 类的静态函数
对静态成员的引用不需要用对象名。
在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员
如果静态成员函数中要引用非静态成员时,可通过对象来引用。
● 请你回答一下为什么析构函数必须是虚函数?为什么C++默认的析构函数不是虚函数 考点:虚函数 析构函数
将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏。
BaseClass* pObj = new SubClass();
delete pObj;
若析构函数是虚函数(即加上virtual关键词),delete时基类和子类都会被释放;
若析构函数不是虚函数(即不加virtual关键词),delete时只释放基类,不释放子类;
C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。
● 请你来说一下函数指针
函数指针是指向函数的指针变量。
函数指针本身首先是一个指针变量,该指针变量指向一个具体的函数。
在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。
作用:通过函数指针,我们可以在函数中使用别的函数作为参数
int Func(int x); /*声明一个函数*/
int (*p) (int x); /*定义一个函数指针*/
p = Func; /*将Func函数的首地址赋给指针变量p*/
p(10)
● 请你来说一下fork函数
不咋用Linux,不太了解这个,哎。。。
https://blog.csdn.net/kxjrzyk/article/details/81603049
一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,
fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;
● 请你来说一下C++中析构函数的作用
析构函数与构造函数对应,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统会自动执行析构函数。
析构函数名也应与类名相同,只是在函数名前面加一个位取反符~。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。
如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数
类析构顺序:1)派生类本身的析构函数;2)对象成员析构函数;3)基类析构函数。
● 请你来说一下静态函数和虚函数的区别
静态函数在编译的时候就已经确定运行时机,虚函数在运行的时候动态绑定。
虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销
● 请你来说一说重载和覆盖
https://blog.csdn.net/xxxluozhen/article/details/4030946
重载:两个函数名相同,但是参数列表不同(个数,类型),返回值类型没有要求
覆盖:子类继承了父类,父类中的函数是虚函数,在子类中重新定义了这个虚函数
1、方法的覆盖是子类和父类之间的关系,是垂直关系;方法的重载是同一个方法之间的关系,是水平关系。
2、覆盖要求参数列表相同;重载要求参数列表不同。
3、被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。
● 请你说一说strcpy和strlen
从src逐字节拷贝到dest,直到遇到'\0'结束,因为没有指定长度,可能会导致拷贝越界
strlen函数是计算字符串长度的函数,返回从开始到'\0'之间的字符个数。
● 请你说一说你理解的虚函数和多态
https://www.cnblogs.com/area-h-p/p/10369709.html
多态的实现:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
主要分为静态多态和动态多态,
静态多态主要是重载,在编译的时候就已经确定;动态多态是用虚函数机制实现的,在运行期间动态绑定。
使用父类的指针去调用子类中重写了的父类中的虚函数的时候,会调用子类重写过后的函数
调用普通重写方法时,会调用父类中的方法
虚函数的实现:
在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中放了虚函数的地址。
当子类继承了父类的时候也会继承其虚函数表,当子类重写父类中虚函数时候,会将其继承到的虚函数表中的地址替换为重新写的函数地址。使用了虚函数,会增加访问内存开销,降低效率。
● 请你来回答一下++i和i++的区别
++i先自增1,再返回,i++先返回i,再自增1
● 请你来说一说++i和i++的实现
int& int::operator++()
{
*this +=1;
return *this;
}
const int int::operator(int)
{
int oldValue = *this;
++(*this);
return oldValue;
}
● 请你来写个函数在main函数执行前先运行
C++:定义全局类变量,在其构造函数会在main()前执行
https://www.iteye.com/blog/tcspecial-2105032
#include<iostream>
using namespace std;
class A{
public:
A(){
printf("before main()\n");
}
~A(){
}
};
A a;//全局
int main() {
printf("main()");
return 0;
}
C:
#include<stdio.h>
__attribute((constructor)) void before(){
printf("%s\n",__FUNCTION__);
}
int main(){
printf("%s",__FUNCTION__);
return 0;
}
● 有段代码写成了下边这样,如果在只修改一个字符的前提下,使代码输出20个hello?
for(int i = 0; i < 20; i--) cout << "hello" << endl;
改:i + 20 或者 -i<20
● 以下四行代码的区别是什么?
const char * arr = "123"; //字符串123保存在常量区,不能改变,有无const效果都一样
char * brr = "123"; //字符串123保存在常量区
const char crr[] = "123"; //123在栈上的
char drr[] = "123"; //字符串123保存在栈区,可以通过drr去修改
● 请你来说一下C++里是怎么定义常量的?常量存放在内存的哪个位置?
对于局部常量,存放在栈区;
对于全局常量,全局/静态存储区;
字面值常量,比如字符串,放在常量区。
● 请你来回答一下const修饰成员函数的目的是什么?
const修饰的成员函数表明函数调用不会对对象做出任何更改,事实上,如果确认不会对对象做更改,就应该为函数加上const限定,这样无论const对象还是普通对象都可以调用该函数。