1.给私有成员变量赋值

已知一个类的结构,但是它所有的成员变量是私有的,有get方法,但是没有set方法,请问如何给成员变量赋值。

答案

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;

class A{
	private:
		int b;
	public:
		int getB(){
			return b;
		}
};


int main(){
	A *a = new A;
	
	int *p = (int *)a;
	*p = 1;
	
	cout<<a->getB()<<endl;
} 

这道题的关键在于,要了解C++实例的内存分布。实现主要是下面两步:

1
2
int *p = (int *)a;  //将a对象强制转换为 int指针,这样p就是指向a的头部
*p = 1;             //将p指向的内存赋值

a实例的内存,其实就存放b一个元素。所以找到b的内存地址,然后强行给地址赋值就可以了。

发散题:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class A{
	private:
		char a;
		int b;
		double c;
	public:
		int getC(){
			return c;
		}
};

如何给这个A类的c 赋值呢?

如果有虚函数怎么办?

其实了解了实质,这些都是在考C++类对象的内存分布,具体可以参考我上一篇文章—-C++类对象的内存分布。


2.C++中为什么函数参数可以传多个,函数返回值只能是一个

C++中函数参数如果少于6个是通过寄存器保存的。超过6个是用栈保存。而且压栈顺序是从右到左。

而C++中函数的返回值是通过 eax 寄存器进行传递的,所以C++函数不支持多个返回值。

PS:go/python中函数可以返回多个参数,是因为他们的返回值时用栈保存的。


3.为什么C++中结构体(struct)可以有构造函数

C里面的结构只是变量的聚合体,结构体不能有函数

C++的struct和class是一回事,不过用struct声明的结构,所有的成员和函数默认都是public的,class里面所有的成员和函数默认都是private;C++的结构可以继承;可有构造和析构函数 以及其他成员函数;

C++中还保留结构体的作用就是为了和C保留。


4.为什么C++中使用C的函数 要有extern

因为C,C++中对函数的命名不一样。

在C语言中,你写了一个函数,假设函数为 void show();

但编译器在存储的时候,会加上自己的规则,所以最后这个函数很可能在编译器存的是 _01_show() (只是举例,真实情况不是这样)

同样C++也会有这样的规则,但是他们规则不一样,所以C++使用C函数的时候,要加上extern,这样才能真正找到这个函数。


5.为什么C不能用C++的动态链接库

因为C++支持重载,C不支持


6.如何判断系统是大端对齐还是小端对齐

借用union这个数据结构判断。

union共同体所有数据成员是共享一段内存,后写入的成员数据将覆盖之前的成员数据,成员数据都有相同的首地址,这是nuion最大的存储特征。union对内存的利用达到不可思议的地步,但只在很特殊的条件下才会使用。union的大小为最大数据成员的大小。

1
2
3
4
5
union Myunion      //定义共用体Myunion
{
    int i;         //int数据成员   
    char ch        //char数据成员
};

上面示例Myunion占4个字节。我们给Myunion i 赋值为1。利用这个就能判断是大端还是小端。

union的成员数据共用内存,并且首地址都是低地址首字节。int i=1时:

​ 大端存储:1存放在最高地址。

​ 小端存储:1存放在最低地址。

所以,我们再次读取char ch时,这个是最低地址首字节,大小端存储会显示不同的值,然后判断系统大小端。


7.编译时多态和运行时多态

(1)编译时的多态性

    编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。

(2)运行时的多态性     运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。C++中,运行时的多态性通过虚函数实现的。


8.static的作用(这个面试经常问)

(1)最重要的一条作用:隐藏

当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。

举例来说明。同时编译两个源文件,一个是a.c,另一个是main.c。

main.c 引用a.c的话,a.c中的static值,static函数。Main.c是看不见的。也不能使用。

(2)static的第二个作用是保持变量内容的持久

未初始化的static数据放置.bss

初始化的放在数据段

static默认初始化为0,如果你定义了一个数据,假设 static int a = 0; //a还是放在.bss段

(3)在类中使用static的性质

在类中声明static变量或者函数时,初始化时使用作用域运算符来标明它所属类,因此,静态数据成员是类的成员,而不是对象的成员,这样就出现以下作用:

    a.类的静态成员函数是属于整个类而非类的对象,所以它没有this指针,这就导致 了它仅能访问类的静态数据和静态成员函数。

    b.不能将静态成员函数定义为虚函数。

    c.由于静态成员声明于类中,操作于其外,所以对其取地址操作,就多少有些特殊 ,变量地址是指向其数据类型的指针 ,函数地址类型是一个“nonmember函数指针”。

    d.static并没有增加程序的时空开销,相反她还缩短了子类对父类静态成员的访问 时间,节省了子类的内存空间。

    e.静态数据成员是静态存储的,所以必须对它进行初始化。 (程序员手动初始化,否则编译时一般不会报错,但

    f.为了防止父类的影响,可以在子类定义一个与父类相同的静态变量,以屏蔽父类的影响。