网易面试1

2016/05/26 C和C++基础

网易面试

网易一面

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类

Search

    Post Directory