热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

剑指offer面试题--类

剑指offer和网上有很多考察类的面试题,我觉得很具有代表性,在这里做一个总结:简答题一:我们可以用static修饰一个类的成员函数,也可以用const修饰类的成员函

       剑指offer和网上有很多考察类的面试题,我觉得很具有代表性,在这里做一个总结:

     简答题一:我们可以用static修饰一个类的成员函数,也可以用const修饰类的成员函数?

     答:错误的。一个类的成员函数使用const修饰,其意义是隐式的在参数中传一个const this*参数。然而,static修饰的成员函数是没有this指针的,与const是相反的。
     简答题二:静态成员函数能不能同时也是虚函数?
     答:不能。调用静态成员函数不需要实例,但调用虚函数需要从一个实例中指向虚函数表的指针以得到函数的地址,因此调用虚函数是需要一个实例的,所以这静态成员函数和虚函数是不能共存的。

 一。剑指offer面试题2:实现一个单例模式的类。

             要求:设计一个类,我们只能生成该类的一个实例。

       该题目要求是这个类只能生成一个实例,所以我们要想办法控制类的构造函数,因为生成实例的入口都是构造函数。

      解法一:将构造函数设置为私有的,对于类的外部将是不可见的。并且将它设置为静态的,只有当条件满足时唯一的调用一次

     

class Singleton
{
public:
static Singleton GetInstance()
{
if(instance==NULL)
{
instance=new Singleton();
}
return instance;
}
private:
static Singleton(){};
static Singleton instance;
}

 
            这种解法思路清晰且直观,但是这只适合单线程的模式下,如果多线程的情况下,会出现两个线程同时访问这个类,当遇到if语句时instance的值还为NULL,两个线程就都创建出一个实例,这就与题目要求不符合。 
 


基于上面的解法一,我们可以得到可行解法二:

    

class Singleton
{
public:
  Singleton  getInstance()
{ if (instance == NULL) {lock(); if (instance == NULL) { instance = new Singleton(); } unlock(); } return instance;}
 private:     static Singleton(){};      static Singleton instance;}
 
    这样只够极低的几率下,通过越过了if (instance == NULL)的线程才会有进入锁定临界区的可能性,这种几率还是比较低的,不会阻塞太多的线程,但为了防止一个线程进入临界区创建实例,另外的线程也进去临界区创建实例,又加上了一道防御if (instance == NULL),这样就确保不会重复创建了。

二。剑指offer面试题48:不能被继承的类

        要求:用C++设计一个不能被继承的类。

      要想要实现一个不能继承的类在C#中是比较简单的,使用关键字sealed就行,所以在这里我们既要实现一个简易版的sealed关键字,是不是很牛的感觉,其实并不是很难得一件事。

       解法一:要想要一个类不能继承,我们首先应该想到的是将类的构造函数设置为私有的,如果一个类的构造函数被设置为私有的,那么它的子类将会无法调用它的构造函数,这和不能继承是一样的效果。同题一一样,我们还想要得到这个类的一个实例并且释放它,这是作为一个类所应该具有的功能。我们可以通过定义公有的静态函数来创建和释放类的实例。

class  A
{
public:
static A * Construct(int n)
{
A *pa = new A;
pa->num = n;
cout<<"num is:"<num< return pa;
}
static void Destruct(A * pIntance)
{
delete pIntance;
pIntance = NULL;
}
private:
A(){}
~A(){}
private:
int num;
};
   这种方法只可以创建堆上的对象,不可以构建栈上的对象。

      这种方法相信大家都可以想到,但是为了打动安静的面试官,我们得拿出点料来才行。

解法二:虚拟继承+友元类

#include
using namespace std;
template
class Base
{
friend T;
private:
Base() {}
~Base() {}
};

class Finalclass : virtual public Base
{
public:
Finalclass() {}
~Finalclass() {}
};
  Finalclass就是那个不能被继承的类。

  继承于Base,Base为虚基类,因为它是Base的友元,所以,它可以访问基类的私有构造函数,以及析构函数。编译运行时是正确的。也就是说,可以创建堆上的对象,并且可以构建栈上的对象。


三。含有指针成员的类的拷贝

      题目:下面是一个数组类的声明和实现,分析这个类有什么问题,并针对问标提出集中解决方案。

      

  Template class Array
{
public:
Array(unsigned arraySize):data(0), size(arraySize)
{
if(size > 0)
data = new T[size];
}
~Array()
{
if(data) delete[] data;
}
void setValue(unsigned index, const T& value)
{
if(index data[index] = value;
}
T getValue(unsigned index) const
{
if(index return data[index];
else
return T();
}
private:
T* data;
unsigned size;
}
    眼尖的朋友应该看出来一点端倪,此类只定义了带参数的构造函数,没有定义无参数的构造函数,还有没有定义拷贝构造函数和复制运算符的重载,系统将会自动生成一个,但是,恰恰系统就会坑了你,此类中有指针的数据成员,这是很危险的

       编译器生成的缺省的构造拷贝函数和拷贝运算符的重载函数,对指针实行的是按位拷贝,仅仅只是拷贝指针的地址,而不会拷贝指针的内容。若执行Array A(10);Array B(A)时。A.data和B.data指向的同一地址。当A或者B中任意一个结束其生命周期调用析构函数时,会删除data。由于他们的data指向的是同一个地方,两个实例的data都被删除了。但另外一个实例并不知道它的data已经被删除了,当企图再次用它的 data的时候,程序就会不可避免地崩溃。

    为了防止这样的情况发生,我们同样将拷贝构造函数和赋值运算符的重载设为私有的函数。
private:
Array(const Array& copy);
const Array& operator = (const Array& copy);
     但是这样的类并不是一个功能齐全的类,所以我们只能自己实现着两个函数来解决问题了:
rray(const Array& copy):data(0), size(copy.size)
{
if(size > 0)
{
data = new T[size];
for(int i = 0; i setValue(i, copy.getValue(i));
}
}
const Array& operator = (const Array& copy)
{
if(this == ©)
return *this;
if(data != NULL)
{
delete []data;
data = NULL;
}
size = copy.size;
if(size > 0)
{
data = new T[size];
for(int i = 0; i setValue(i, copy.getValue(i));
}
}





     


推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
author-avatar
Jasper-ling玲
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有