C++ interview questions面试问题

问题1 :from http://www.careercup.com/question?id=17227667

高盛面试题

What will be the value of the variable 'var1' in class A?  答案d
a) 6 
b)7 
c) 5 
d) undefined

代码中注释的内容是我后来添加的

分析:调用子类的构造函数时,(1)会先调用父类构造函数构造父类成员部分,可见下面代码中子类构造函数b的参数初始化列表中调用父类构造函数。

而这时var2变量还未初始化,调用父a构造函数var2给var1赋值时,var1变量值为某个未定义的值

(2)接着调用构造函数初始化列表中的var2(d++),把d的值赋给var2,d再自增(3)最后调用子类构造函数体(中括号括起来的部分)的内容

注:构造函数初始化列表中的内容比构造函数体的内容先执行


#include<iostream>
using namespace std;
class a{ 
public: 
	int var1; 
	a(int var) 
	{ 
		var1 = var; 
		//cout<<var1<<endl;
		//cout<<"parent constructor"<<endl;
	} 
}; 
class b: public a 
{ 
public: 
	int var2; 
	b(int d):var2(d++) , a(var2++) 
	{ 
	
		//cout<<"child constructor"<<endl;
	} 
}; 
int main()
{ 
	b obj1(8); 
} 




问题2

高盛笔试题

http://www.careercup.com/question?id=17223669

class a{
public:
	int a;
	virtual void sum() {
		printf("sum");
	}
};

class b : public a {
public:
	int b;
	virtual void sum() {
		printf("sum of class b");
	}
};

void main() {
	b aptr;
	a *bptr;
	bptr = &aptr;
	bptr->sum();
}
Output of the above program?
输出sum of class b

分析:参见C++中的虚函数机制

类似代码

B为A的父类,Fun1为虚函数,传递引用与指针效果相同

B b; 
A &a =b; 
a.Fun1()

也是调用的子类的函数




结构体对齐(structure alignment )

可以参见维基百科http://en.wikipedia.org/wiki/Data_structure_alignment

结构体中每个成员的对齐值(一般是该成员类型大小,若该数据成员是个数组,对齐值是该数组中数据类型的对齐值,而不是数组占据大小的字节值),相当于该数据成员离结构体起始地址的偏移量是对齐值的整数倍。

比如int类型对齐值为1 byte。加入结构体有个数据成员int arr[4]; 

arr也是4字节对齐,而不是16字节对齐。相当于该数组中每个int类型元素是4字节对齐即可

结果体总长度:该长度需为结构体成员中最大的对齐值的整数倍。

The sizeof value for any structure is the offset of the final member, plus that member's size, rounded up to the nearest multiple of the largest member alignment value or the whole structure alignment value, whichever is greater.(cite from MSDN http://msdn.microsoft.com/en-us/library/83ythb65.aspx

The type of each member of the structure usually has a default alignment, meaning that it will, unless otherwise requested by the programmer, be aligned on a pre-determined boundary. The following typical alignments are valid for compilers from

Microsoft (Visual C++), Borland/CodeGear (C++Builder), Digital Mars (DMC) and GNU (GCC) when compiling for 32-bit x86:

  • char (one byte) will be 1-byte aligned.
  • short (two bytes) will be 2-byte aligned.
  • An int (four bytes) will be 4-byte aligned.
  • long (four bytes) will be 4-byte aligned.
  • float (four bytes) will be 4-byte aligned.
  • double (eight bytes) will be 8-byte aligned on Windows and 4-byte aligned on Linux (8-byte with -malign-doublecompile time option).
  • long long (eight bytes) will be 8-byte aligned.
  • long double (ten bytes with C++Builder and DMC, eight bytes with Visual C++, twelve bytes with GCC) will be 8-byte aligned with C++Builder, 2-byte aligned with DMC, 8-byte aligned with Visual C++ and 4-byte aligned with GCC.
  • Any pointer (four bytes) will be 4-byte aligned. (e.g.: char*, int*)

the total size of the structure should be a multiple of the largest alignment of any structure member

比如

struct s{

char ch[6];

int data;
}

ch对齐值1(开始理解错误了,以为ch占据了6个字节,对齐值便为6了,其实不然,以为相当于连续分配6个字节,ch数组中的每个元素均为1字节对齐的),

ch后是6字节偏移量,而int是4字节对齐的,需在ch后填充2个字节,之后int占据4个字节,这时struct大小为12字节,结构体中最大对齐值为int类型,为

4字节,12是4字节的整数倍,所以不用再填充。该结构体占据12字节。

相当于

struct s{

char ch[6];

ch   padding[2];

int data;
}





sizeof

指针类型的sizeof在32位机器上都是4

比如char *c=(char*)malloc(10*sizeof(char))

sizeof(c) //结果为4


struct product{
char name[10];
float price;
};

printf("%d\n",sizeof(product));//输出为16
product *p=(product*)malloc(sizeof(product));
printf("%d\n",sizeof(p));//输出为4

该结构体占据16byte,name占据10字节,而float是4字节对齐,name后面需填充2字节。float占据4字节。总的为10+2+4=16字节,是最大对齐值类型float的整数倍,因此结构体尾部不需要填充。总的占据16字节

只要是指针变量sizeof均为4(32位机器上),不管该指针指向的是个int,char等基本类型还是结构体等变量


class Car{
char name[10];
int price;
static int i;

};

sizeof(Car)=16,静态成员不会被计算在内



为什么是复制构造函数的参数是引用参数

如果不使用引用参数的话,该传递相当于值传递,需在调用构造函数时创建参数的副本,这样又会去调用复制构造函数。导致递归,无限循环无法结束



复制构造函数与赋值操作符

复制构造函数针对的是之前未创建的对象,赋值操作符针对的是之前已经创建(存在的对象),而不是看是否有等于号(=)的出现

比如

string str="abcdef";

在调用该语句前str对象不存在,此句是完成str对象的创建,是复制初始化的形式,调用的是拷贝构造函数。

而比如

string str;

str="ghjkl";

这时调用的便是赋值操作符,因为str对象在str="ghjkl"此语句前已存在



shallow copy vs deep copy

浅拷贝与深拷贝

当类中有动态分配的成员,即指针类型成员时。需要使用深拷贝

因为浅拷贝会导致不同的对象的动态成员指向同一个地址,当其中一个对象调用析构函数的时候,另一个对象的动态成员所指向的地址已经被系统回收了。



对于以下的类声明,哪种使用方式是正确的

class Tank{

public:

virtual void Run()=0;

virtual void F ire()=0;

}


A .Tank myTank; myTank.Run()                B  void Repair(Tank tank){.....}

C A* pTank=GetOneTank(); pTank->Fire();   D void Refuel(Tank &tank)


答案为C,D

含有纯虚函数的类为抽象类

A 抽象类无法实例化,A错误   B传递的是抽象类的对象,参数是值调用的形式(call by value).而抽象类本身无法实例化,在函数体内根本无法创建参数的拷贝

C可以通过子类的指针调用虚方法     D可以传递抽象类的指针或引用,D正确

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值