C++ 题目(一)

题目(一)求输出结果

#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;
bool
Fun1 (char *str)
{
  printf ("%s\n", str);
  return false;
}

bool
Fun2 (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是从虚函数表中得到函数地址的。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值