C++ 题目(一)

来源:互联网 发布:ade7755校验网络 编辑:程序博客网 时间:2024/06/05 02:54

题目(一)求输出结果

#include <iostream>using namespace std;struct Point3D{  int x;  int y;  int z;};int main (){  Point3D *pPoint = NULL;  int offset = (int) (&(pPoint)->z);  printf ("%d", offset);  return 0;}


答案:输出8。由于在pPoint->z的前面加上了取地址符号,运行到此时的时候,会在pPoint的指针地址上加z在类型Point3D中的偏移量8。由于pPoint的地址是0,因此最终offset的值是8。&(pPoint->z)的语意是求pPoint中变量z的地址(pPoint的地址0加z的偏移量8),并不需要访问pPoint指向的内存。只要不访问非法的内存,程序就不会出错。这也是求在一个结构体(类中)某个变量偏移位置的方法。

题目(二)

#include <iostream>using namespace std;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 main (){  A a;  a.Print ();  return 0;}

答案:输出n1是一个随机的数字,n2为0。在C++中,成员变量的初始化顺序与变量在类型中的申明顺序相同,而与它们在构造函数的初始化列表中的顺序无关。因此在这道题中,会首先初始化n1,而初始n1的参数n2还没有初始化,是一个随机值,因此n1就是一个随机值。初始化n2时,根据参数0对其初始化,故n2=0。

题目(三)

#include <iostream>using namespace std;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 main (){  A a = 10;  A b = a;  b.Print ();  return 0;}

答案:编译错误。在复制构造函数中传入的参数是A的一个实例。由于是传值,把形参拷贝到实参会调用复制构造函数。因此如果允许复制构造函数传值,那么会形成永无休止的递归并造成栈溢出。因此C++的标准不允许复制构造函数传值参数,而必须是传引用或者常量引用。在Visual Studio和GCC中,都将编译出错。gcc中编译为“错误:无效的构造函数:您要的可能是 ‘A (const A&)’”。

题目(四)

#include <iostream>using namespace std;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 ();}

答案:输出B::Fun with number 10。由于a是一个指向B实例的引用,因此在运行的时候会调用B::Fun。但缺省参数是在编译期决定的。在编译的时候,编译器只知道a是一个类型a的引用,具体指向什么类型在编译期是不能确定的,因此会按照A::Fun的声明把缺省参数number设为10。这一题的关键在于理解确定缺省参数的值是在编译的时候,但确定引用、指针的虚函数调用哪个类型的函数是在运行的时候。

题目(五)

#include <iostream>using namespace std;boolFun1 (char *str){  printf ("%s\n", str);  return false;}boolFun2 (char *str){  printf ("%s\n", str);  return true;}int main (){  bool res1, res2;  res1 = (Fun1 ("a") && Fun2 ("b")) || (Fun1 ("c") || Fun2 ("d"));  res2 = (Fun1 ("a") && Fun2 ("b")) && (Fun1 ("c") || Fun2 ("d"));  return res1 || res2;}

答案:打印出4行,分别是a、c、d、a。
在C/C++中,与、或运算是从左到右的顺序执行的。在计算rest1时,先计算Fun1(“a”) && Func2(“b”)。首先Func1(“a”)打印出内容为a的一行。由于Fun1(“a”)返回的是false, 无论Func2(“b”)的返回值是true还是false,Fun1(“a”) && Func2(“b”)的结果都是false。由于Func2(“b”)的结果无关重要,因此Func2(“b”)会略去而不做计算。接下来计算Fun1(“c”) || Func2(“d”),分别打印出内容c和d的两行。在计算rest2时,首先Func1(“a”)打印出内容为a的一行。由于Func1(“a”)返回false,和前面一样的道理,Func2(“b”)会略去不做计算。由于Fun1(“a”) && Func2(“b”)的结果是false,不管Fun1(“c”) && Func2(“d”)的结果是什么,整个表达式得到的结果都是false,因此Fun1(“c”) && Func2(“d”)都将被忽略。

题目(六)

#include <iostream>using namespace std;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 main (){  Base b;  b.print ();  Derived d;  d.print ();  return 0;}

 

答案:输出两行,分别是Base::doPrint和Derived::doPrint。在print中调用doPrint时,doPrint()的写法和this->doPrint()是等价的,因此将根据实际的类型调用对应的doPrint。所以结果是分别调用的是Base::doPrint和Derived::doPrint2。如果感兴趣,可以查看一下汇编代码,就能看出来调用doPrint是从虚函数表中得到函数地址的。

 

原创粉丝点击