1. 运行下面的C++代码,得到的结果是什么?
#include "stdafx.h"
#include<iostream>
using namespace std;
class A
{
private:
int m_value;
public:
A(int value)
{
m_value = value;
}
void Print1()
{
printf("hello world");
}
void Print2()
{
printf("%d", m_value);
}
virtual void Print3()
{
printf("hello world");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* pA;
pA->Print1();
pA->Print2();
pA->Print3();
return 0;
}
答案是:Print1调用正常,打印出hello world,但运行至Print2时,程序崩溃。
调用Print1时,并不需要pA的地址,因为Print1的函数地址是固定的。编译器会给Print1传入一个this指针,该指针为NULL,但在Print1中该this指针并没有用到。
只要程序运行时没有访问不该访问的内存就不会出错,因此运行正常。
在运行print2时,需要this指针才能得到m_value的值。由于此时this指针为NULL,因此程序崩溃了。
对于Print3这一虚函数,C++在调用虚函数的时候,要根据实例(即this指针指向的实例)中虚函数表指针得到虚函数表,再从虚函数表中找到函数的地址。由于这一步需要访问实例的地址(即this指针),而此时this指针为空指针,因此导致内存访问出错。
2. 运行下面的C++代码,得到的结果是什么?
#include<iostream>
using namespace std;
class A
{
public:
A()
{
Print();
}
virtual void Print()
{
cout<<"A is constructed."<<endl;
}
};
class B: public A
{
public:
B()
{
Print();
}
virtual void Print()
{
cout<<"B is constructed."<<endl;
}
};
int main()
{
A* pA = new B();
delete pA;
return 0;
}
先后打印出两行:A is constructed. B is constructed. 调用B的构造函数时,先会调用B的基类A的构造函数。
然后在A的构造函数里调用Print。由于此时实例的类型B的部分还没有构造好,本质上它只是A的一个实例,他的虚函数表指针指向的是类型A的虚函数表。
因此此时调用的Print是A::Print。接着调用类型B的构造函数,并调用Print。此时已经开始构造B,并且虚函数表的指针已指向类B的虚函数表地址,因此此时调用的Print是B::Print。
3. 运行下面的C++代码,输出是什么?
class A{
private:
int n1;
int n2;
public:
A():