- List item
嵌入式工程师综合笔试题之C++
1、 初始化和赋值的区别是什么?定义和声明的区别是什么?
赋值操作是在两个已经存在的对象间进行的,而初始化是创建一个新的对象并且初始化来源于另一个存在的对象.初始化是在编译时进行的,而赋值是在函数或程序运行时进行.
- 定义也是申明,extern声明不是定义,及不分配内存空间.
- 声明有初始化就被当做定义.
- 带有{}就是定义,否则就是声明.
- 除非有extern关键字,否则就是变量的定义.
2、 什么是“引用”?引用和指针的区别?声明和使用“引用”要注意哪些问题?
引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样. - 指针是实体,引用是别名没有空间;
- 引用定义时必须初始化,而指针不用.
- 指针可以改而引用不行.
- 引用不能为空,而指针可以.
- Sizeof引用是引用的对象的大小,而sizeof指针指针本身的大小.
- 不能为NULL引用,引用必须与一块合法存储单元关联.
- 如果返回是动态分配的内存对象,必须使用指针,使用引用会内存泄漏.
- 对引用的操作既是对变量本身的操作.
规则: - 不能返回局部变量的引用.
- 不能返回函数内部new分配的内存引用.
- 可以返回内成员的引用,最好为const.
- 流操作重载返回值声明为引用.
- 四则运算不能返回引用.
3、 将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?
类型&函数名(参数){}
在内存中不会产生返回值副本(因为这点不能返回一个局部变量的引用);
规则: - 不能返回局部变量的引用.
- 不能返回函数内部new分配的内存引用.
- 可以返回内成员的引用,最好为const.
- 流操作重载返回值声明为引用.
- 四则运算不能返回引用.
4、 new/delete 和 malloc/free的区别是什么?
5、 内联函数和一般函数的区别在什么地方?内联函数、enum和宏定义的区别是什么?
内联函数和普通函数相比可以加快程序的运行速度,在调用内联函数的时候不需要中断,在编译的时候直接镶嵌在目标代码中.而且内联函数要进行类型检查.
6、 C++中const的作用有哪些,若在类中有这样的函数定义void show() const {},请问在这里const的作用是什么? 在c++与C中的const有什么区别?
- 用于常量的定义.
- 用于修饰函数形式参数.
- 用于修饰函数的返回值(且该返回值只能被赋值给加const修饰的同类型指针).
- 修饰类的成员函数(函数定义体)
说明此函数是一个常量成员函数(此函数必须是一个类的成员函数),它表示const成员函数不能修改类中的成员.
7、 C++中static的作用有哪些? - 隐藏,仅限于本文件使用,对其他的源文件隐藏.(对于函数来说static的作用仅限于隐藏)
- 保持变量内容的持久(全局生命周期).
- 程序刚开始运行就完成初始化,初始化值为0,且只初始化一次.
- 静态数据成员(归对象所共有,而不是只属于某个对象的成员,如果值发生改变则各个对象中这个数据成员的值都同时改变了。类内声明,类外定义)
- 静态成员函数(静态成员函数与非静态成员函数的根本区别是:非静态成员函数有this指针,而静态成员函数没有this指针,静态成员函数主要用来访问静态数据成员,而不访问非静态成员)
8、 C++有哪些性质(面向对象的特点)?
封装(隐藏细节,使得代码模块化),继承(拓展已存在的代码模块),多态(为了实现接口重用)
9、 C++ 中的 class 和 struct 的区别? - 默认继承权限不同,class默认继承是private,而struct默认继承是public.
- Class可以用于定义模板参数,但是关键字struct不能同于定义模板参数.
保留struct的原因: - 保证C语言的向下兼容.
- 对struct定义的扩展使C语言的代码能够更容易的被移植到C++中.
10、 private、public、protected权限有什么区别?
Public在程序中类的外部是可以访问的.继承的时候权限都不变.
Protected保护成员变量或函数与私有成员十分相似,但是保护成员在派生类是可以访问的.继承的时候public变为protected.
Private 私有成员或函数在类的外部是不可访问的.甚至不能查看.只有友元函数可以访问私有成员.继承的时候全部变为private.
11、 C++中参数传递的方式有哪些?区别是什么? - 值传递:传递的是副本,并非本身.
- 地址传递:使用变量地址做参数,改变时发生变化的是本身.
- 引用传递:变量取一个别名,实际上形参和实参是同一个东西.
12、 哪些初始化必须使用初始化列表? - 常量成员
- 引用类型
- 没有默认构造函数的类类型.
13、 C++空类默认哪些成员函数?定义一个类,写出他们的函数声明?
空构造,析构,拷贝构造,重载赋值操作符,取址运算符,取址运算符const
函数名(); 函数名(const 函数名&); ~函数名(); 函数名&operator=(const 函数名 &) 函数名operator&(); const 函数名 operator&() const;
14、 基类的析构函数不是虚函数可能会出现什么问题?哪些函数不能声明为虚函数?
用基类类型指针绑定派生类实例,析构的时候,如果基类析构函数不是虚函数,则只会析构基类,不会析构派生类对象,从而造成内存泄漏.
普通函数,友元函数,内联函数,静态成员函数,构造函数不能为虚函数.
15、 构造函数和析构函数的特点是什么?它和其他成员函数的区别在哪儿? - 构造与析构的名字必须与类名相同.析构要在函数名前加~.
- 构造函数可以有任意类型的参数,但不能指定返回类型.(他有隐含的返回值),析构函数不能有参数也不能有返回值.
- 构造函数是特殊的成员函数,函数体可写在类体内,也可以写在类体外.
- 构造函数可以重载,构造函数不能继承.析构只能有一个.
- 它们都不能被显示的调用.
- 在声明类的时候如果没有定义构造和析构,编译器就会自动生成默认形式的构造析构函数.
- 除了无参构造函数是默认构造意外,带有全部默认参数值的构造也是默认构造.
- 自动调用:构造在定义类对象时自动调用.析构在对象生命结束时,delete对象指针或指向对象基类类型指针和父类析构时调用子类析构的时候都会调用析构函数.
16、 什么是友元函数和友元类,他们的作用是什么?友元函数和一般成员函数的区别是什么?
友元函数是指某些虽然不是类成员却能够访问类的所有成员的函数
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员不能被继承).
友元提供了在不同类的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制.
成员函数是类定义的一部分,通过对象来调用.成员函数可以隐式访问调用对象的成员,而无法使用成员操作符.友元函数不是类的组成部分.所以被称为直接函数调用.不能隐式访问类成员,而必须将成员操作符用于作为参数传递的对象.
17、 简述构造函数中深拷贝与浅拷贝的区别,并实现一个简单的深拷贝构造函数
浅拷贝只是对指针进行复制,复制完成后两个指针指向同一个内存空间,而深拷贝不止对指针进行复制,也对指针指向的内容进行复制,深拷贝之后,两个指针指向不同的地址内存空间,但内容相同.
18、 虚函数、纯虚函数、虚基类分别是什么东西?分别在何时使用?
虚基类:当有钻石继承的时候公共基类会产生多个实例(多个副本),若只想保留基类的一个实例,可以将公共基类声明为虚基类.虚基类是为了只实例化一次基类存在的.
虚函数: 在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数.在实现动态联编的时候使用.
纯虚函数: 在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做.
19、 派生类实例化对象和释放对象是构造函数和析构函数的调用顺序?为什么?
20、 什么是静态联编?什么是动态联编?
静态联编(早绑定):在编译时就已经确定调用和被调用两者关系.通过函数重载和泛型编程实现.
动态联编(晚绑定):在程序运行时确定调用和被调用关系. 通过类的继承和虚函数实现
21、 什么是虚函数表?虚函数表的作用是什么?
虚函数表是一块连续的内存,每个内存单元中记录一个JMP指令的地址
作用: - 子类重写父类虚函数后,在子类父类中调用的虚函数都是子类的虚函数.
- 子类重写父类虚函数后,父类指针指向父类,调用父类虚函数,子类指针指向子类,调用子类虚函数,父类指向子类调用子类的虚函数.
- 父类指针可以指向父类对象和子类对象.
- 子类指针可以指向子类对象,但子类指针不可以指向父类对象.
22、 隐藏、重写、重载三者区别是什么?
23、 继承的方式有哪些,各自有什么特点?
公有继承:各个成员的权限没有变化.
保护继承:public权限变成protected权限,其他权限不变.
私有继承:基类中所有的权限都变为private权限.
24、 C++多态分哪两种方式?两种方式各自使用了什么实现的?
静态多态:通过函数重载或者泛型编程实现.(编译阶段确定调用和被调用关系)
动态多态:通过继承和虚函数实现.(在运行阶段确定调用和被调用关系)
25、 什么是抽象类,抽象类和一般类有什么区别?
抽象类是包含一种或多种抽象方法的类,它本身不需要构造实例.定义抽象类后,其他类可以对它进行扩充并实现其中的抽象方法. - 抽象类不能被实例化.
- 抽象类可以有抽象方法,抽象方法只需声明
- 含有抽象方法的类必须声明为抽象类
- 抽象的子类必须实现抽象父类中所有抽象方法,否则这个子类也是抽象类.
- 抽象方法不能被声明为静态.
- 抽象方法不能用private和final修饰
26、 已知 MyString 类定义如下:
class MyString
{
public:
MyString(const char *str = NULL); // 通用构造函数
MyString(const MyString &another); // 拷贝构造函数
~ MyString(); // 析构函数
MyString & operater=(const MyString &rhs); // 赋值函数
private:
char *m_data; // 用于保存字符串
};
尝试写出类的成员函数实现。并简述三个成员函数什么时候被调用。
27、 简述下面类中的错误,并进行更改?
class person {
public:
person() {};
int age;
int #
const int hear;
static char *p;
static void show() { cout << age << endl;
};
28、 写出以下程序的输出结果:
char str1[] = “abc”; char str2[] = “abc”; const char str3[] = “abc”; const char str4[] = “abc”;
const char *str5 = “abc”; const char *str6 = “abc”; char *str7 = “abc”; char str8 = “abc”;
cout << ( str1 == str2 ) << endl;
cout << ( str3 == str4 ) << endl;
cout << ( str5 == str6 ) << endl;
cout << ( str7 == str8 ) << endl;
29、 C++实现一个Vector类。
template class Vector {
public:
Vector(intsize=0);
Vector(constVector&rhs);
~Vector();
const Vector& operator=(const Vector& rhs);
T& operator[](int index);
bool isEmpty()const;
int size()const;
void push_back(T t);
T& back();
private:
T objects;
int Size;
};
30、 代码如下:
class A{
public:
int m;
A(){ cout<<”A()”<<endl;}
void print(){ cout<<”A print()”<<endl;}
A(){cout<<”A()”<<endl;}
};
int main()
{
A pa = 0;
pa->print();
}
上面代码是否有问题?如果有问题,请修改。如果没有问题,会打印什么结果?
31、 写出以下程序的输出结果:
class A {
public:
virtual void g() { cout <<“A::g”<< endl; }
private:
virtual void f() { cout <<“A::f”<< endl; }
};
class B : public A {
void g() { cout <<“B::g”<< endl; }
virtual void h() { cout <<“B::h”<< endl; }
};
typedef void( Fun )( void );
int main()
{
B b;
Fun pFun;
for(int i = 0 ; i < 3; i++) {
pFun = ( Fun )( ( int * ) * ( int )( &b ) + i );
pFun();
}
32、 C++实现队列和循环队列
33、 实现一个模版函数swap用与交换任意两个非自定义数据类型对象的值;
34、 写一个单例模式的类。
35、 写一个简单工厂模式。
36、 实现一个观察者模式。
37、 C++实现模板类List<>
38、 定义一个int类型std::vector的变量,这个变量增加5个值(1,2,3,4,5),然后遍历该变量,遍历中如果值为2将其删除,反之打印输出