目录
第一天总结
1.局部变量能否和全局变量重名?
答案: 能,局部会屏蔽全局。要用全局变量,需要使用"::"。 局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。 对于有些编译器而言,在同一个函数内 可以 定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内。
参考代码:
int A = 10;
int main()
{
int A = 9;
cout << A << endl; //输出A等于9
cout << ::A << endl; //输出A等于10
return 0;
}
2.不能把字符串"HELLO!"赋给数组b的语句是(B)
答案:
A. char b[10]={'H','E','L','L','O','!','\0'};
B. char b[10];b="HELLO!";
C. char b[10];strcpy(b,"HELLO!");
D. char b[10]="HELLO!";
A. 空格符号和空字符是不一样的,在ASCII里面,空格(space)符号的ASCII码是0x20,而空字符是0x0,完全不一样的2个字符。
空字符一般来描述一个字符串的结尾,其实是控制符的一种,但不能理解为没有字符,应该理解为代表什么都没有的字符。好比回车0x0A和换行0x0D虽然不显示,但是也是控制字符的一种。
字符串的概念: 在C语言中,字符串是指由若干个有效字符(其中包括字母、数字、转义字符、等)组成的系列,以’\0’作为字符串结束标志。’\0’是一个“空操作”字符,它不做任何操作,只是一个标志。’\0’的代码值为0,它不计入串的长度。
B. b是表示数组的首地址,不能赋值。
C. C 库函数 char *strcpy(char *dest, const char *src) 把 src 所指向的字符串复制到 dest。 需要注意的是如果目标数组 dest 不够大,而源字符串的长度又太长,可能会造成缓冲溢出的情况。
3.变量void (*s[5])(int)表示意思为(函数指针数组)
答案: 这是一个标准的函数指针数组,s[5]说明s是一个数组,数组的内容是void (*)(int)类型的函数指针,该指针指向的函数参数为int,返回值为void。
函数指针数组:
char * (*pf)(char * p)
定义的是一个函数指针pf,既然pf 是一个指针,那就可以储存在一
个数组里:char * (*pf[3]) (char * p);
(*pf[3]) 是一个指针素组, (pf[3])(char * p) 数组内
有3 个指向函数的指针,char * (*pf[3]) (char * p)
函数指针指向函数返回的是 char 类型。
函数指针数组的指针:
顾名思义这个指针指向 函数指针数组,下面就定义一个简单的函数指针数组指针:
char * (*(*pf)[3])(char * p);
(*pf)[3] 数组指针,pf 是指针,pf 指向一个包含了3个元素的
数组。(*(*)[3])(char * p)
这个数组里面存的是指向函数的指针。
char * (*(*pf)[3])(char * p);
这些指针指向返回值类型为char *、参数为 char * 的函数。
4.以下程序的输出是:
#include <iostream>
using namespace std;
template <typename T>
void print(T t)
{
cout<<"The value is "<<t<<endl;
}
template <>
void print<char *>(char* c)
{
cout<<"The string is " << c <<endl;
}
int main()
{
char str[] = "TrendMicro[char]";
unsigned char ustr[] = "TrendMicro[unsigned char]";
print(str);
print(ustr);
return 0;
}
The string is TrendMicro[char]<br>The value is TrendMicro[unsigned char]
答案: 模板函数和普通函数都符合条件时,优先执行普通函数
5.分析一下这段程序的输出:
#include<iostream>
using namespace std;
class B
{
public:
B()
{
cout << "default constructor" << " ";
}
~B()
{
cout << "destructed" << " ";
}
B(int i): data(i)
{
cout << "constructed by parameter" << data << " ";
}
private: int data;
};
B Play( B b)
{
return b;
}
int main(int argc, char *argv[])
{
B temp = Play(5);
return 0;
}
constructed by parameter5 destructed destructed
答案:
- 调用Play函数需要将5隐式类型转换为Play函数中的形参b,会调用B的B(int i): data(i),打印“constructed by parameter5”。
- Play函数返回时需要调用B的复制构造函数给对象temp初始化。
- Play函数返回后需要调用b的析构函数,将Play函数的形参释放,打印“destructed”。
- main函数返回后需要释放temp,打印“destructed”。
6.下面可用于字符串复制的函数有:
答案: strcpy,sprintf,memcpy
memcpy()函数:
从数组a复制k个元素到数组b中:memcpy(b,a,sizeof(int/double)*k)
数组a全部复制到数组b中:memcpy(b,a,sizeof(a))
strcpy()函数:
char *strcpy(char *destin, char *source);
功能:将source指向的字符串拷到destin,会覆盖之前的,source包含'\0'
sprintf()函数:
把信息输出到字符串,保证字符串足够大
char a[20];
memset(a,0,sizeof(a));
sprintf(a,"%d%d%d%d",4,5,6,7); for(int i=0;i<sizeof(a);i++){
printf("%d ",a[i]);
}
//输出20位 52 53 54 55 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
补充: strcmp()函数:
int strcmp(char * str1,char * str2);
功能: 比较两个字符串str1,str2
返回: str1<str2,返回负数;str1=str2,返回 0;str1>str2,返回正数,,按位比较
strstr()函数:
char* strstr(char* str1,char* str2);
功能:找出str2字符串在str1字符串中第一次出现的位置(不包括str2的串结束符)
返回: 返回该位置的指针,如找不到,返回空指针
char b[20]="abcdef";
printf("position:%s\n",strstr(b,"bc")); //position:bcdef
7.char str[]=”Hello”,sizeof(str)=?
答案: 6。
sizeof
计算长度包括字符串结束符\0,strlen
不包括。
实际存储为{'H','e','l','l','o','\0'}
,所以是6个
#include "stdio.h"
int main() {
char str[] = "hello";
char *s = "hello";
int a[] = {3, 5, 7};
printf("%d\n%d\n%d\n", sizeof(str), sizeof(s), sizeof(a));//输出6, 4, 12
return 0;
}
8.下面关于虚函数和函数重载的叙述不正确的是?
答案: 虚函数不是类的成员函数。
A: 虚函数不是类的成员函数
B: 虚函数实现了C++的多态性
C: 函数重载允许非成员函数,而虚函数则不行
D: 函数重载的调用根据参数的个数、序列来确定,而虚函数依据对象确定
解释:
虚函数也是类的成员函数,A说法是不正确的;
虚函数和函数重载都实现了C++的多态性,但表现形式不一样,函数重载调用根据参数个数、参数类型等进行区分,而虚函数则是根据动态联编来确定调用什么,故BD说法正确
函数重载可以是类的成员函数也可以是非成员函数,比如:
int fun(int a);
int fun(int a, int b);
这就是非成员重载,虚函数必须是成员函数了,否则就失效了, 所以C对 。
多态性分为编译时多态性和运行时多态性,
编译时多态性通过静态编联完成,例如函数重载,运算符重载;
运行时多态性则是动态编联完成,主要通过虚函数来实现;
函数重载不需要是成员函数,在类外声明或定义的函数同样可以对其进行重载;
重载的调用主要根据参数个数,参数类型,参数顺序来确定, 函数重载是忽略返回值的。
扩展一下, 提醒大家注意虚函数和纯虚函数的区别
虚函数可以在子类中进行重载,也可以不重载而沿用父类中的方法。但纯虚函数必须重载,因为在其声明类中没有函数实现。vritual void func()=0;
包含纯虚函数的类为抽象类,抽象类不能声明对象,只能作为基类 。
9. 经 过 以 下 语 句 定 义 后 , 表 达 式z+=x>y?++x:++y 的值为()?
int x=1,y=2,z=3;
答案: 6。
赋值运算符<逻辑运算符<关系运算符<算数运算符,原式相当于z+=(x>y?++x,++y) 所以结果为6。
这里考察的是运算符运算规则的问题,影响运算符求值顺序的主要是运算符的优先级和结合性。
-
优先级:主要是不同优先级运算符之间的运算规则;
-
结合性:主要是优先级相同时运算符需要遵守的运算规则 。
本题中的表达式,有以下4种运算符,它们是具有不同优先级的运算符,因此这里只需考虑优先级,无需考虑结合性复合赋值运算符 += 关系运算符 > 条件运算符 ? : 增强运算符 ++
优先级从高到低:增强运算符、关系运算符、条件运算符、赋值运算符
因此求值顺序应该是
第一步,同时求++x和++y;求得表达式++x为2,且x变为2;表达式++y为3,且y变为3;
第二步,是判断x>y(注意:此时的x和y已经是进行过第一步后的x和y值);即2 > 3
第三步,是条件运算;因为2 > 3是F,因此条件表达式的值为++y,即3
第四步,是复合赋值运算 +=即z += 3,z = z + 3。
最后得出 z = 6
10. 下列情况中,不会调用拷贝构造函数的是(B)
A: 用一个对象去初始化同一个类的另一个新对象时
B: 将类的一个对象赋值给该类的另一个对象时
C: 函数的形参对象,调用函数进行形参和实参结合时
D: 函数的返回值是类的对象,函数执行返回调用时
解释:
调用拷贝构造函数的3中情况:
- 用一个对象去初始化同一个类的另一个新对象时;
- 函数的形参对象,调用函数进行形参和实参结合时 ;
- 函数的返回值是类的对象,函数执行返回调用时将一个对象赋值给另一个对象,两个对象都存在,调用的是赋值构造函数,不涉及内存的分配。当被赋值的对象不存在调用的是拷贝构造函数。
C++拷贝构造函数详解C++拷贝构造函数详解