经典面试题:类和继承

1.实现一个不能被继承的类

(1)思路:

将构造函数定义为私有的,因为子类创建对象需要先调用父类的构造函数,如果父类中的构造函数被定义为私有的,就不可以被别的类访问

(2)代码实现:

#include <iostream>
using namespace std;

class A
{
public:
    static A* fun1()//new一个对象
    {
        return new A;
    }
    static A fun2()//使用匿名对象拷贝构造
    {
        return A();
    }
private:
    A(){}
    int _a;
};

class B :public A
{
private:
    int _b;
};

int main()
{
    B b;
    return 0;
}

这里写图片描述

2.实现一个类,定义出的对象只能在堆上

(1)思路:

借助上一题的思想,使用动态分配空间new的方法创建对象

(2)普通版

class A
{
public:
    static A* fun()
    {
        return new A;
    }
private:
    A(){}
    int _a;
};

这个代码有缺陷,虽然能保证构造的对象都是堆上的,但是不能防止拷贝构造的对象在栈上,例如:
A* pa=A::fun();//在堆上
A a1(*pa);//在栈上
A a2=*pa;//在栈上
这里写图片描述

(3)进阶版

<1>思路:

防拷贝的两个条件,缺一不可:
①只声明拷贝构造不实现
②将拷贝构造声明称私有的

<2>为何两个条件缺一不可

只有条件①的话,因为是声明,所以有可能会在别的地方(比如全局域)对拷贝构造再次实现

//只有条件①的情况
#include <iostream>
using namespace std;

class A
{
public:
    static A* fun()
    {
        return new A;
    }
    A(const A& a);
    A& operator=(const A& a);
private:
    A(){}
    int _a;
};

int main()
{
    A* pa = A::fun();
    A a1(*pa);
    A a2 = *pa;
    return 0;
}

这里将拷贝构造函数只声明不定义,确实可以限制拷贝构造函数的调用,如下图:
这里写图片描述

//只有条件①的缺陷验证
#include <iostream>
using namespace std;

class A
{
public:
    static A* fun()
    {
        return new A;
    }
    A(const A& a);
    A& operator=(const A& a);
private:
    A(){}
    int _a;
};

//在类外实现拷贝构造函数
A::A(const A& a){}
A& A::operator=(const A& a)
{
    return *this;
}


int main()
{
    A* pa = A::fun();
    A a1(*pa);
    A a2 = *pa;
    return 0;
}

只有条件①的话,防止不了在类外再次对拷贝构造函数的实现的情况,如下图:
这里写图片描述

<3>进阶版代码

//下面的代码是验证条件①和②能限制拷贝构造的使用
//使得该类定义的对象只能在堆上
//编译器报错,说明验证正确
#include <iostream>
using namespace std;

class A
{
public:
    static A* fun()
    {
        return new A;
    }

private:
    A(){}
    //将拷贝构造的声明设为私有的
    A(const A& a);
    A& operator=(const A& a);
    int _a;
};

//在类外实现拷贝构造函数
A::A(const A& a){}
A& A::operator=(const A& a)
{
    return *this;
}

int main()
{
    A* pa = A::fun();
    A a1(*pa);
    A a2 = *pa;
    return 0;
}

这里写图片描述

3.实现一个类,定义出的对象只能在栈上

跟上题相似,直接上代码

#include <iostream>
using namespace std;

class A
{
public:
    static A& fun()
    {
        return A();
    }

private:
    A(){}
    int _a;
};

int main()
{
    A pa = A::fun();

    return 0;
}

4.实现一个类,定义出的对象不能在堆上

(1)思路:

将动态分配空间的操作符声明为私有的,即可防止类构造对象时在堆上开空间的行为

(2)代码实现

class A
{
private:
    void* operator new(size_t size);
    void operator delete(void *p);
    int _a;
};

这里写图片描述

猜你喜欢

转载自blog.csdn.net/w_y_x_y/article/details/80032655