现在的位置: 首页 > 综合 > 正文

360面试小结

2018年11月07日 ⁄ 综合 ⁄ 共 2311字 ⁄ 字号 评论关闭

一、struct和class的区别

C++中的struct对C中的struct进行了扩充,它已经不再只是一个包含不同数据类型的数据结构了,它已经获取了太多的功能。
struct能包含成员函数吗? 能!struct能继承吗? 能!struct能实现多态吗? 能!

struct几乎和class拥有一样的功能。

最本质的一个区别就是默认的访问控制: 

默认的继承访问权限

struct是public的,class是private的。struct和class可以相互继承。
你可以写如下的代码:
struct A
{
  char a;
};
struct B : A
{
  char b;
};

这个时候B是public继承A的。

如果都将上面的struct改成class,那么B是private继承A的。这就是默认的继承访问权限。 

所以我们在平时写类继承的时候,通常会这样写:
class B : public A

就是为了指明是public继承,而不是用默认的private继承。

 

当然,到底默认是public继承还是private继承取决于子类而不是基类

我的意思是,struct可以继承class,同样class也可以继承struct,那么默认的继承访问权限是看子类到底是用的struct还是class。如下:

struct A{};

class B : A{};     // private继承
struct C : B{}; // public继承

 

但我上面却没有用“唯一”,而是说的“最本质”,那是因为,它们确实还有另一个区别,虽然那个区别我们平时可能很少涉及。

那就是:“class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。这一点在Stanley B.Lippman写的Inside the C++ Object Model有过说明。 


还有默认数据的访问权限,struct中的成员默认是public,外部可访问;class中的成员变量默认是private,外部是不能直接访问的,正通过公有成员函数访问和修改。


二、new和malloc的区别

1.malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存

2.对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。

3.因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。 
4.C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。 
5.new可以认为是malloc加构造函数的执行。new出来的指针是直接带类型信息的。而malloc返回的都是void*指针new/delete在实现上其实调用了malloc,free函数,可以把其看成是malloc加上构造函数。

6.new建立的对象你可以把它当成一个普通的对象,用成员函数访问,不要直接访问它的地址空间;malloc分配的是一块内存区域,就用指针访问好了,而且还可以在里面移动指针。

7.new 建立的是一个对象;malloc分配的是一块内存.

三、const的用法

const int * const ptr;    // 这个用得最多,两个const不解释

const douvle data = 3.1415;

类成员函数中const的使用一般放在函数体后,形如:void fun() const; 
任何不会修改数据成员的函数都因该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其他非const成员函数,编译器将报错,这大大提高了程序的健壮性。

const成员变量只对某个对象而言是常量,对于整个类来说是可以变化不同的,每个生成的对象可以不同,用成员列表进行初始化


四、多态中析构函数可以不是虚么

基类的指针指向派生类对象,并用基类的指针删除派生类对象。这样会造成局部释放,内存泄露。

析构函数的工作方式是:最底层的派生类的析构函数最先被调用,然后调用每一个基类的析构函数
因为在C++中,当一个派生类对象通过使用一个基类指针删除,而这个基类有一个非虚的析构函数,则结果是未定义的。运行时比较有代表性的后果是对象的派生部分不会被销毁。然而,基类部分很可能已被销毁,这就导致了一个古怪的“部分析构”对象,这是一个泄漏资源。排除这个问题非常简单:给基类一个虚析构函数。于是,删除一个派生类对象的时候就有了你所期望的正确行为。将销毁整个对象,包括全部的派生类部分。
但是,一般如果不做基类的类的析构函数一般不声明为虚函数,因为虚函数的实现要求对象携带额外的信息,这些信息用于在运行时确定该对象应该调用哪一个虚函数。典型情况下,这一信息具有一种被称为 vptr(virtual
table pointer,虚函数表指针)的指针的形式。vptr 指向一个被称为 vtbl(virtual table,虚函数表)的函数指针数组,每一个包含虚函数的类都关联到 vtbl。当一个对象调用了虚函数,实际的被调用函数通过下面的步骤确定:找到对象的 vptr 指向的 vtbl,然后在 vtbl 中寻找合适的函数指针。这样子会使类所占用的内存增加。
定义纯虚析构函数(pure virtual destructor),含有纯虚函数的类是ABC(Abstract
Base Class)。

抱歉!评论已关闭.