把自己印象笔记中所记录的一些C++知识点整合了一下,可用于面试前对C++知识的快速回顾。
不过并不全,只是自己笔记中的摘要,重要的还是系统和踏实地学习。
每个知识点不分顺序。
1.typeid是什么
2.define的一些注意点
#define a 10
void
foo();
void
prin();
int
main()
{
prin();
printf
(
"%d "
, a);
foo();
printf
(
"%d "
, a);
}
void
foo()
{
#undef a
#define a 50
}
void
prin()
{
printf
(
"%d "
, a);
//此处的a已经被替换
}
|
3.重载,重定义,重写是什么?
4.C++中的空类,默认产生哪些类成员函数?
5.运算符重载
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class z;
ostream & operator<< (ostream &out,z z1);
class z{
public:
int real,imag;
z(int r=0,int i=0):real(r),imag(i){};
z operator+ (const z &z1) const;
z operator- ();//无参数,前置负号
z &operator++ () ; //前置,即++z
z operator++ (int) ; //后置,即z++
friend ostream & operator<< (ostream &out,z z1);
void show();
};
//友元函数,不用加::
ostream & operator<< (ostream &out,z z1)
{
out<<"("<<z1.real<<","<<z1.imag<<")";
return out;
}
z z::operator+ (const z &z1) const
{
return z(this->real+z1.real,imag+z1.imag);
}
z &z::operator++ ()
{
real++;
imag++;
return *this;
}
z z::operator++ (int )
{
return z(real++,imag++);
}
z z::operator- ()
{
return z(-real,-imag);
}
void z::show()
{
printf("(%d,%d)\n",real,imag);
}
int main()
{
z a(1,5),b(3,1);
cout<<"a+b=";
(a+b).show();
(a++).show();
a.show();
(++b).show();
b.show();
(-b).show();
cout<<"a="<<a<<endl;
}
6.模板类和类模板的区别
- //声明一个函数模版,用来比较输入的两个相同数据类型的参数的大小,class也可以被typename代替,
- //T可以被任何字母或者数字代替。
- template <class T>
- T min(T x,T y)
- {
- return(x<y)?x:y;
- }
- template <class T>
- class Base
- {
- public :
- T a ;
- Base(T b) {
- a = b ;
- }
- T getA(){ return a ;} //类内定义
- void setA(T c);
- };
- template <class T> //模板在类外的定义
- void Base<T>::setA(T c)
- {
- a = c ;
- }
7.static 和 const 的作用
8.String类的实现
1
2
3
4
5
6
7
8
9
10
|
class
String
{
public
:
String(
const
char
*str = NULL);
// 普通构造函数
String(
const
String &other);
// 拷贝构造函数
~ String(
void
);
// 析构函数
String & operator =(
const
String &other);
// 赋值函数
private
:
char
*m_data;
// 用于保存字符串
};
|
参考答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
//普通构造函数
String::String(
const
char
*str)
{
if
(str==NULL)
{
m_data =
new
char
[1];
// 得分点:对空字符串自动申请存放结束标志'\0'的空
//加分点:对m_data加NULL 判断
*m_data =
'\0'
;
}
else
{
int
length =
strlen
(str);
m_data =
new
char
[length+1];
// 若能加 NULL 判断则更好
strcpy
(m_data, str);
}
}
// String的析构函数
String::~String(
void
)
{
delete
[] m_data;
// 或delete m_data;
}
//拷贝构造函数
String::String(
const
String &other)
// 得分点:输入参数为const型
{
int
length =
strlen
(other.m_data);
m_data =
new
char
[length+1];
//加分点:对m_data加NULL 判断
strcpy
(m_data, other.m_data);
}
//赋值函数
String & String::operate =(
const
String &other)
// 得分点:输入参数为const型
{
if
(
this
== &other)
//得分点:检查自赋值
return
*
this
;
delete
[] m_data;
//得分点:释放原有的内存资源
int
length =
strlen
( other.m_data );
m_data =
new
char
[length+1];
//加分点:对m_data加NULL 判断
strcpy
( m_data, other.m_data );
return
*
this
;
//得分点:返回本对象的引用
}
|
9.assert的作用
- void* memcpy(void *dst, const void *src, size_t count)
- {
- //安全检查
- assert( (dst != NULL) && (src != NULL) );
- unsigned char *pdst = (unsigned char *)dst;
- const unsigned char *psrc = (const unsigned char *)src;
- //防止内存重复
- assert(!(psrc<=pdst && pdst<psrc+count));
- assert(!(pdst<=psrc && psrc<pdst+count));
- while(count--)
- {
- *pdst = *psrc;
- pdst++;
- psrc++;
- }
- return dst;
- }
10.函数指针的用法
函数指针
11.枚举变量
enum e{a,b,c=5,d,e} x;
int main()
{
char *s="abcde";
x=(enum e)d; //d代表6,a代表0,b代表1
switch(x)
{
case a:cout<<"a"<<endl;break;
case b:cout<<"b"<<endl;break;
case c:cout<<"c"<<endl;break;
case d:cout<<"d"<<endl;break;
case e:cout<<"e"<<endl;break;
}
}
12.构造函数 析构函数 是不是虚函数
13.特殊类型变量
Volatile
14.二重指针寻址
1
2
3
4
5
6
7
8
9
10
11
|
#include <stdio.h>
void
f(
char
**p){
*p +=
2
;
}
main()
{
char
*a[] = {
"123"
,
"abc"
,
"456"
},**p;
p = a;
f(p);
printf(
"%s\r\n"
,*p);
}
输出3
*p+=2;就相当于*p=*p+2;
其中*p指向字符串“123”的第一个元素,即‘1’,指针p向后移两个元素的地址,即指向‘3’
而*(p+2)才是基于p每次向后移一个字符串的长度,即*(p+2)指向“456”
|
15.STL一级容器
16.多重继承的优缺点
多继承或者继承都是为了实现类的重用和封装,优点就是减少代码量,实现算法抽象等;缺点(多继承)就是容易造成名字空间冲突(尤其对于MFC类或者其他同一个基类的一般不能使用多继承),或者所称的菱形继承。建议看看《设计模式》这本书,一般可以通过其他方法(聚合等)实现多继承的话应该避免多继承。
17.动态联编(多态)
18.转义字符
19.重载的注意事项
20.指针数组
21.数组取地址的问题
1
2
3
|
int
a[
5
]={
1
,
2
,
3
,
4
,
5
};
int
*ptr=(
int
*)(&a+
1
);
printf(
"%d,%d"
,*(a+
1
),*(ptr-
1
));
int a[5]={0,1,2,3,4};
cout<<*(a++)<<endl; //此处a++是错的
作为数组名,a是一个
常量指针
,a指向的内容可改,但是a指针的指针地址不可改。
应该让int *p=a,那么即可执行p++
当a传入函数时,退化为指针,那么就可以执行a++了
char *b="abc"
则*b="123"是错的,内容不可改,指向可改。
但b=c是对的。
|
22.读文件时的定位问题
#include <stdio.h>
main()
{
FILE * fp;
int
i,a[
6
]={
1
,
2
,
3
,
4
,
5
,
6
},k;
fp = fopen(
"data.dat"
,
"w+"
);
for
(i=
0
;i<
6
;i++)
{
fseek(fp,0L,
0
); //移动到文件开头,偏移0
fprintf(fp,
"%d\n"
,a[i]); //
rewind (fp); //也是回到文件开头
fscanf(fp,
"%d"
,&k);
}
fclose(fp);
printf(
"%d\n"
,k);
}
的输出结果是6
|
23.结构体大小判断
32位和64位系统的区别在于long和指针,32位下他们是4字节,64位下他们是8字节
short都是2字节,float都是4字节,double都是8字节,long long都是8字节
short int 2字节
long long int 8字节
遵循两条原则:一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
二、结构体大小必须是所有成员大小的整数倍。
struct A{
longa1;
shorta2;
inta3;
int*a4;
};
例如求上面这个结构体A的sizeof大小,在64位下
a1的移量为0,长度为8
a2的偏移量为0+8=8,长度为2
a3的偏移量为8+2=10,不符合int长度4的倍数,故偏移量变成12,,长度为4
a4的偏移量为12+4=16,长度为8
故总大小为16+8=24,24是所有成员大小的整数倍,故A的大小为24
23.结构体大小判断
#include <stdio.h>
main()
{
FILE * fp;
int
i,a[
6
]={
1
,
2
,
3
,
4
,
5
,
6
},k;
fp = fopen(
"data.dat"
,
"w+"
);
for
(i=
0
;i<
6
;i++)
{
fseek(fp,0L,
0
); //移动到文件开头,偏移0
fprintf(fp,
"%d\n"
,a[i]); //
rewind (fp); //也是回到文件开头
fscanf(fp,
"%d"
,&k);
}
fclose(fp);
printf(
"%d\n"
,k);
}
的输出结果是6
|