网易面试
网易一面
1、多态性都有哪些?
静态(函数重载)和动态(虚函数)
2、动态绑定怎么实现?
基类与派生类指针和引用的转换问题
3、类型转换有哪些?
static_cast、const_cast、dynamic_cast和reinterpret_cast
** 4、操作符重载(+操作符),具体如何去定义**
#include <iostream>
using namespace std;
struct point{
int x;
int y;
};
point operator+(const point &p1,const point &p2){
point np;
np.x=p1.x+p2.x;
np.y=p1.y+p2.y;
return np;
}
int main(){
point p1,p2;
p1.x=1;
p1.y=2;
p2.x=3;
p2.y=4;
point p3=p1+p2;
cout<<p3.x<<" "<<p3.y<<endl;
system("pause");
}
5、内存对齐的原则?
(原则叙述了一下并举例说明)
(1)、每个数据成员的偏移量必须是MIN(内存存取粒度n,该数据成员的自身长度)的倍数。
(2)、结构体第一个数据成员的地址必须是MIN(内存存取粒度n,结构体中数据成员最大长度)的倍数。
(3)、结构体长度一定是MIN(内存存取粒度n,结构体中数据成员最大长度)的整数倍。
6、模版怎么实现?
7、指针和const的用法
8、虚函数、纯虚函数、虚函数与析构函数?
纯虚函数如何定义,为什么析构函数要定义成虚函数
virtual float area() const{return 0;}
9、内联函数
讲了一下内联函数的优点以及和宏定义的区别
10、const和typedef
主要讲了const的用处,有那些优点
11、排序算法有哪些?快速排序怎么实现的?最好时间复杂度,平均时间复杂度
12、链接指示:extern “C”(作用)
C++程序有时需要调用其他语言编写的函数,最常见的是调用C语言编写的函数。像所有其他名字一样,其他语言中的函数名字也必须在C++中进行声明,并且该声明必须指定返回类型和形参列表。对于其他语言编写的函数来说,编译器检查其调用方式与处理普通C++函数的方式相同,但生成的代码有所区别。C++使用链接指示(linkage directive)指出任意非C++函数所用的语言。
13、c语言和c++有什么区别?
大体讲了一下,继承、多态、封装、异常处理等
网易二面
1、strcpy函数的编写
char *strcpy(char *dst,const char *src){
if((dst==NULL)||(src==NULL))
return "error";
int len=0;
char *strtemp=dst;
while(src[len]!='\0'){
strtemp[len]=src[len];
len++;
}
strtemp[len]='\0';
return strtemp;
}
2、数据结构中二叉树的非递归遍历
3、继承机制中对象之间是如何转换的?
4、继承机制中引用和指针之间如何转换?
5、虚函数,虚函数表里面内存如何分配?
6、如何实现只能动态分配类对象,不能定义类对象?
(把如何只能动态分配和只能静态分配都讲了一下)
只能动态分配的方法:
#include <iostream>
using namespace std;
class A{
protected:
A(){}
~A(){}
public:
static A* create(){
return new A();
}
void destroy(){
delete this;
}
};
int main(){
A a; //报错 无法调用构造函数
A *a=A::create(); //调用成功
system("pause");
}
只能静态分配对象的方法:
#include <iostream>
using namespace std;
class A{
private:
void* operator new(size_t t){} //函数的第一个参数与返回值都是固定的
void operator delete(void *ptr){} //重载了new,就需要重载delete
public:
A(){}
~A(){}
};
int main(){
A a=new A(); //报错
A a;
system("pause");
}
7、stl有哪些容器,对比vector和set?
8、红黑树的定义和解释?
结点不是黑色就是红色、根结点是黑色、叶子结点是黑色、如果结点是红色,则子结点一定是黑色、从某一个结点开始,沿着各个路径到达叶子结点,则黑色结点的数目一定相等。
9、const关键字的作用?
(const变量、const成员函数、变量、对象,函数值传递,和define的区别)
10、静态成员函数和数据成员有什么意义?
静态数据成员:加强对象之间的数据共享。
静态成员函数:专门访问静态数据成员。
11、模版特化的概念,为什么特化?
C++中经常为了避免重复的编码而需要使用到模板,这是C++泛型编程不可或缺的利器。然而通常又有一些特殊的情况,不能直接使用泛型模板展开实现,这时就需要针对某个特殊的类型或者是某一类特殊的类型,而实现一个特例模板————即模板特化。通常会使用到模板特化的有(应该也只能有)类模板和函数模板。
1).模板的特化是在已有的通用模板不再适用于一些特殊的类型参数时,而针对这些特殊的类型参数专门实现的模板。
2).模板的偏特化是指需要根据模板的部分参数进行特化。
3).函数调用匹配的规则是:先精确匹配类型参数,然后匹配函数模板,最后通过参数隐式类型转换进行匹配。
12、explicit是干什么用的?
例如下面例子中C的构造函数C(int i)就是,既可以用来作为构造器,又可以实现隐式转换C c=2;但是有时这并不是我们想要的,就可以将这个构造函数声明为explicit,以避免将构造函数作为隐式类型转换符来使用。Copy constructor也是同样的,如果Copy constructor被声明为explicit,则这个类对象不能用于传参和函数返回值。但是仍然可以直接调用。
13、strcpy返回类型是干嘛用的?
为了实现链式操作,将目的地址返回
char * strcpy( char *strDest, const char *strSrc ) {
////对源地址和目的地址加非0断言
assert( (strDest != NULL) && (strSrc != NULL) );
char *address = strDest;
while( (*strDest++ = * strSrc++) != '\0’ );
return address;
}
14、内存溢出有那些因素?
数据类型超过了计算机字长的界限就会出现数据溢出的情况。导致内存溢出问题的原因有很多,比如:
(1) 使用非类型安全(non-type-safe)的语言如 C/C++ 等。
(2) 以不可靠的方式存取或者复制内存缓冲区。
(3)编译器设置的内存缓冲区太靠近关键数据结构。
因素分析
1).内存溢出问题是 C 语言或者 C++ 语言所固有的缺陷,它们既不检查数组边界,又不检查类型可靠性(type-safety)。众所周知,用 C/C++ 语言开发的程序由于目标代码非常接近机器内核,因而能够直接访问内存和寄存器,这种特性大大提升了 C/C++ 语言代码的性能。只要合理编码,C/C++应用程序在执行效率上必然优于其它高级语言。然而,C/C++ 语言导致内存溢出问题的可能性也要大许多。其他语言也存在内存溢出问题,但它往往不是程序员的失误,而是应用程序的运行时环境出错所致。
2).当应用程序读取用户(也可能是恶意攻击者)数据,试图复制到应用程序开辟的内存缓冲区中,却无法保证缓冲区的空间足够时(换言之,假设代码申请了 N 字节大小的内存缓冲区,随后又向其中复制超过 N 字节的数据)。内存缓冲区就可能会溢出。想一想,如果你向 12 盎司的玻璃杯中倒入 16 盎司水,那么多出来的 4 盎司水怎么办?当然会满到玻璃杯外面了!(比如递归)
3).最重要的是,C/C++编译器开辟的内存缓冲区常常邻近重要的数据结构。假设某个函数的堆栈紧接在在内存缓冲区后面时,其中保存的函数返回地址就会与内存缓冲区相邻。此时,恶意攻击者就可以向内存缓冲区复制大量数据,从而使得内存缓冲区溢出并覆盖原先保存于堆栈中的函数返回地址。这样,函数的返回地址就被攻击者换成了他指定的数值;一旦函数调用完毕,就会继续执行“函数返回地址”处的代码。非但如此,C++ 的某些其它数据结构,比如 v-table 、例外事件处理程序、函数指针等,也可能受到类似的攻击。
15、new与malloc的区别,delet和free的区别?
16、为什么要用static_cast转换而不用c语言中的转换?
基本变量的强制转换和static_cast是没有区别的,但是static_cast转换数据安全;可以一眼看出来这里有强制转换。
c++引进了类的时候就需要static_cast转换了,因为它会检查类型看是否能转换:
#include <iostream>
using namespace std;
class A{};
class B{};
int main(){
A* a= new A;
B* b = (B*)a; //编译通过 但这显然是错误的
B* b = static_cast<B*>(a); //无法编译通过
system("pause");
}
17、异常机制是怎么回事?
try throw catch
18、迭代器删除元素的会发生什么?
19、必须在构造函数初始化列表里进行初始化的数据成员有哪些?
const 引用
常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面
引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化
20、类的封装:private,protected,public
21、auto_ptr类