问题16:在C++中定一个不能被继承的类
解法:容易想到的就是将这个类的构造函数和析构函数都设为私有的。这样继承的类就无法调用父类的构造函数和析构函数,编译时就会报错。但是不能被继承的类如何产生对象呢?可以利用静态函数,它与类的对象无关,可以直接通过类的作用域直接调用。
- class FinalClass
- {
- public:
- static FinalClass* GetInstance()
- {
- return new FinalClass;
- }
- static void DeleteInstance(FinalClass* pInstance)
- {
- delete pInstance;
- pInstance = NULL;
- }
- private:
- FinalClass() {} //私有的构造函数
- ~FinalClass() {} //私有的析构函数
- };
解法:其实就是设计模式中的单例模式。这里给出两种方式。
方式一:类似问题16,将构造函数和析构函数定义为私有的,定义一个静态的类对象指针。通过静态函数进行初始化。
- //Single.h定义
- #pragma once
- class Singleton
- {
- public:
- static Singleton* GetInstance();
- private:
- Singleton();
- ~Singleton();
- static Singleton *singleton;
- };
- //Singleton.cpp定义
- Singleton* Singleton::singleton = NULL; //静态成员初始化
- Singleton::Singleton()
- {
- }
- Singleton::~Singleton()
- {
- }
- Singleton* Singleton::GetInstance()
- {
- if(singleton == NULL)
- singleton = new Singleton();
- return singleton;
- }
方式二:利用局部静态变量只初始化一次的性质,可以这样来实现。
- class Singleton
- {
- private:
- Singleton(){}
- public:
- static Singleton* GetInstance()
- {
- static Singleton singleton; //局部静态变量
- return &singleton;
- }
- };
问题18:写一个程序,要求功能,求出用1、2、5这三个数不同个数组合的和为100的组合数。如100个1是一个组合,20个5是另外一个组合。用C++实现。
解法:最简单的用穷举法,三层循环就可以解决了。代码如下,这样效率太低了。循环次数为101 * 51 * 21。 这其实就是个数学问题,就是求 x + 2y + 5z = 100解的个数。变化一下,x + 5z = 100 - 2y,这个式子表明 x + 5y只能是偶数。以z为循环变量,有下述规律。
z=0, x=100, 98, 96, ... 0
z=1, x=95, 93, ..., 1
z=2, x=90, 88, ..., 0
z=3, x=85, 83, ..., 1
z=4, x=80, 78, ..., 0
......
z=19, x=5, 3, 1
z=20, x=0
因此,组合总数为100以内的偶数+95以内的奇数+90以内的偶数+...+5以内的奇数+1,
即为:(51+48)+(46+43)+(41+38)+(36+33)+(31+28)+(26+23)+(21+18)+(16+13)+(11+8)+(6+3)+1
第二种方法的循环次数仅为21次。代码如下:
- int C100_Solution1()
- {
- int num = 0;
- for(int x = 0; x <= 100; x++)
- for(int y = 0; y <= 50; y++)
- for(int z = 0; z <= 20; z++)
- num += ((x + 2 *y + 5 *z) == 100);
- return num;
- }
- int C100_Solution2()
- {
- int num = 0;
- for (int i = 0; i <= 100;i += 5)
- num += (i + 2)/2;
- return num;
- }
问题19:实现一个strcpy函数。
解答:看似简单,其实考查的是基本功。需要注意这么几点:(1)指针为空判断。(2)实现链式操作。(3)C的字符串以'\0'结尾。(4)源指针加const修饰。下面给出一个实现。
- char* strcpy(char *pDest, const char *pSrc)
- {
- assert(pDest!=NULL && pSrc!=NULL);
- char* tmp = pDest;
- while((*pDest++ = *pSrc++) != '\0')
- ;
- return tmp;
- }
问题20:static和const关键字尽可能多的作用。
static关键字至少有下列作用:
(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。
const关键字至少有下列作用:
(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
(2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;
(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为"左值"。