1) #include<iostream> using namespace std; class A { public: virtual void Fun(int number = 10) { std::cout << "A::Fun with number " << number << endl; } }; class B:public A { public: virtual void Fun(int number = 20) { std::cout << "B::Fun with number " << number << endl; } }; int main() { B b; A &a = b; A *aa = new B; aa->Fun(); a.Fun(); } 答案:输出B::Fun with number 10。由于a是一个指向B实例的引用,因此在运行的时候会调用B::Fun。但缺省参数是在编译期决定的。在编译的时候,编译器只知道a是一个类型a的引用,具体指向什么类型在编译期是不能确定的,因此会按照A::Fun的声明把缺省参数number设为10 2) 题目(一):C++中我们可以用static修饰一个类的成员函数,也可以用const修饰类的成员函数(写在函数的最后表示不能修改成员变量,不是指写在前面表示返回值为常量)。请问:能不能同时用static和const修饰类的成员函数? 分析:答案是不可以。C++编译器在实现const的成员函数的时候为了确保该函数不能修改类的实例的状态,会在函数中添加一个隐式的参数const this*。但当一个成员为static的时候,该函数是没有this指针的。也就是说此时static的用法和static是冲突的。 3) 首先:我们要知道什么是类的实例化,所谓类的实例化就是在内存中分配一块地址. 那我们先看看一个例子: #include<iostream.h> class a {}; class b{}; class c:public a{ virtual void fun()=0; }; class d:public b,public c{}; int main() { cout<<"sizeof(a)"<<sizeof(a)<<endl; cout<<"sizeof(b)"<<sizeof(b)<<endl; cout<<"sizeof(c)"<<sizeof(c)<<endl; cout<<"sizeof(d)"<<sizeof(d)<<endl; return 0;} 程序执行的输出结果为: sizeof(a) =1 sizeof(b)=1 sizeof(c)=4 sizeof(d)=8 为什么会出现这种结果呢?初学者肯定会很烦恼是吗?类a,b明明是空类,它的大小应该为为0,为什么 编译器输出的结果为1呢?这就是我们刚才所说的实例化的原因(空类同样可以被实例化),每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址.所以a,b的大小为1. 而类c是由类a派生而来,它里面有一个纯虚函数,由于有虚函数的原因,有一个指向虚函数的指针(vptr),在32位的系统分配给指针的大小为4个字节,所以最后得到c类的大小为4. 类d的大小更让初学者疑惑吧,类d是由类b,c派生迩来的,它的大小应该为二者之和5,为什么却是8 呢?这是因为为了提高实例在内存中的存取效率.类的大小往往被调整到系统的整数倍.并采取就近的法则,里哪个最近的倍数,就是该类的大小,所以类d的大小为8个字节. 4) #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); } }; int main(int argc, char* argv[]) { A* pA = NULL; pA->Print1(); pA->Print2(); return 0; } 分析:答案是Print1调用正常,打印出hello world,但运行至Print2时,程序崩溃。Print1的调用情况和上面的题目一样,不在赘述。由于Print2是虚函数。C++调用虚函数的时候,要根据实例(即this指针指向的实例)中虚函数表指针得到虚函数表,再从虚函数表中找到函数的地址。由于这一步需要访问实例的地址(即this指针),而此时this指针为空指针,因此导致内存访问出错。 5) #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(int argc, char* argv[]) { A a; a.Print(); return 0; } //答案:输出n1是一个随机的数字,n2为0。在C++中,成员变量的初始化顺序与变量在类型中的申明顺序相同,而与它们在构造函数的初始化列表中的顺序无关。因此在这道题中,会首先初始化n1,而初始n1的参数n2还没有初始化,是一个随机值,因此n1就是一个随机值。初始化n2时,根据参数0对其初始化,故n2=0。 6) #include "iostream" using namespace std; int SizeOf(char pString[]) { return sizeof(pString); } int main(int argc, char* argv[]) { char* pString1 = "google"; int size1 = sizeof(pString1); int size2 = sizeof(*pString1); char pString2[100] = "google"; int size3 = sizeof(pString2); int size4 = SizeOf(pString2); printf("%d, %d, %d, %d \n", size1, size2, size3, size4); //cout << *pString1 << endl; //cout << pString1 << endl; return 0; } 答案:4, 1, 100, 4。pString1是一个指针。在32位机器上,任意指针都占4个字节的空间。*pString1是字符串pString1的第一个字符。一个字符占一个字节。pString2是一个数组,sizeof(pString2)是求数组的大小。这个数组包含100个字符,因此大小是100个字节。而在函数SizeOf中,虽然传入的参数是一个字符数组,当数组作为函数的参数进行传递时,数组就自动退化为同类型的指针。 7) #include "iostream" using namespace std; class A { public: A() { std::cout << "A is created." << std::endl; } /* virtual */ ~A() { std::cout << "A is deleted." << std::endl; } }; class B : public A { public: B() { std::cout << "B is created." << std::endl; } ~B() { std::cout << "B is deleted." << std::endl; } }; int main(int argc, char* argv[]) { A* pA = new B(); delete pA; cout << "-------------------------------" << endl; return 0; } 答案:输出三行,分别是:A is created. B is created. A is deleted。用new创建B时,回调用B的构造函数。在调用B的构造函数的时候,会先调用A的构造函数。因此先输出A is created. B is created.
C++笔试题1
最新推荐文章于 2025-06-16 15:47:23 发布