bool Fun1(char* str)
{
printf("%s\n", str);
return false;
}
bool Fun2(char* str)
{
printf("%s\n", str);
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
bool res1, res2;
res1 = (Fun1("a") && Fun2("b")) || (Fun1("c") || Fun2("d"));
res2 = (Fun1("a") && Fun2("b")) && (Fun1("c") || Fun2("d"));
return res1 || res2;
}
[分析]考察逻辑运算符&&和||的运算顺序和短路特性。
&&和||从左到右进行运算。
短路特性:对于&&,如果左侧为false,则不再计算右侧表达式;对于||,如果左侧为true,则不再计算右侧表达式。
第一条res1 = ( Fun1("a") && Fun2("b") ) || ( Fun1("c") || Fun2("d") );
Fun1("a")执行结果为false,根据&&特性,右侧Func2("b")将不执行;Fun1("a")&&Fun2("b")结果为false;
根据||特性,需要计算右侧表达式.
Fun1("c")为false,需要进一步计算||右侧的Fun2("d"),结果为true,因此res1结果为false || true == true.
第二条res2 = (Fun1("a") && Fun2("b")) && (Fun1("c") ||Fun2("d"));
由上可知Fun1("a")&&Fun2("b")仅计算Fun1("a"),结果为false;
且由于其为false,导致第二个&&右侧部分不需要计算;
[答案]
a
c
d
a
2.运行下面的C++代码,打印的结果是什么?
class Base
{
public:
void print() { doPrint();}
private:
virtual void doPrint() {cout << "Base::doPrint" << endl;}
};
class Derived : public Base
{
private:
virtual void doPrint() {cout << "Derived::doPrint" << endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
Base b;
b.print();
Derived d;
d.print();
Base t = (Base)d;
t.print();
Base *p = &d;
p->print();
return 0;
}
[分析]
考察C++的函数覆盖以及动态绑定特性。
[答案]
Base::doPrint
Derived::doPrint
Base::doPrint
Derived::doPrint
3.运行如下的C++代码,输出是什么?
class A
{
public:
virtual void Fun(int number = 10)
{
std::cout << "A::Fun with number " << number;
}
};
class B: public A
{
public:
virtual void Fun(int number = 20)
{
std::cout << "B::Fun with number " << number;
}
};
int main()
{
B b;
A &a = b;
a.Fun();
}
[分析]
考察C++的动态绑定特性。由于使用了引用,所以动态绑定生效,所以调用类B的Fun输出B::Fun with number比较好理解。问题是输出的是10而不是20.
这是由于函数的缺省参数是在编译时刻确定的,因此结果是类A的缺省参数10.
[答案]
B::Fun with number 10
4.运行如下的C代码,输出是什么?
char* GetString1()
{
char p[] = "Hello World";
return p;
}
char* GetString2()
{
char *p = "Hello World";
return p;
}
int _tmain(int argc, _TCHAR* argv[])
{
printf("GetString1 returns: %s. \n", GetString1());
printf("GetString2 returns: %s. \n", GetString2());
return 0;
}
[分析]考察自动变量的生存期和字符串常量。
GetString1中,通过局部数组变量保存字符串,当函数结束时,空间释放,因此再次访问此区域,结果是随机的;
GetString2中,字符指针指向的字符串常量存放在全局数据区,并不会因为函数的退出而释放该空间,因此能够得到正常输出。
[答案]
GetString 1 returns: 随机字符串
GetString 2 returns: Hello World.
5.运行下图中C代码,输出的结果是什么?
int _tmain(int argc, _TCHAR* argv[])
{
char str1[] = "hello world";
char str2[] = "hello world";
char* str3 = "hello world";
char* str4 = "hello world";
if(str1 == str2)
printf("str1 and str2 are same.\n");
else
printf("str1 and str2 are not same.\n");
if(str3 == str4)
printf("str3 and str4 are same.\n");
else
printf("str3 and str4 are not same.\n");
return 0;
}
[分析]
考察内容和上题类似。str1和str2比较的是两个数组的首地址,可见是不相同的。
str3和str4的值是字符串常量的首地址,因为两个字符串完全相同,因此会共享,两个指针值相同。
[答案]
str1 and str2 are not same.
str3 and str4 are same.
6.运行下图中的C++代码,输出是什么?6.
#include <iostream>
class A
{
private:
int n1;
int n2;
public:
A(): n2(0), n1(n2 + 2)
{
}
void Print()
{
std::cout << "n1: " << n1 << ", n2: " << n2 << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
a.Print();
return 0;}
[分析]
考察成员变量的初始化顺序。
在C++中,成员变量的初始化顺序与变量在类型中的申明顺序相同,而与它们在构造函数的初始化列表中的顺序无关。因此在这道题中,会首先初始化n1,而初始n1的参数n2还没有初始化,是一个随机值,因此n1就是一个随机值。初始化n2时,根据参数0对其初始化,故n2=0。
[答案]
n1:随机, n2:0
#include <iostream>
class A
{
private:
int value;
public:
A(int n)
{
value = n;
}
A(A other)
{
value = other.value;
}
void Print()
{
std::cout << value << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a = 10;
A b = a;
b.Print();
return 0;
}