面试题:类和继承

更多c++知识:c++目录索引


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

思路:

子类继承父类,子类的构造函数就是合成的;当子类创建对象时,先调用父类的构造函数,在调用自己的构造函数,故此不能继承,将父类的构造函数设为私有成员,这样子类就不能访问,不能创建对象,因此也就不能继承

代码:

class AA
{
public:

    static AA* GetObject()
    {
        return new AA;//直接new一个AA对象
    }

    /*static AA GetObject()
    {
        return AA();//调用拷贝构造,返回一个匿名对象
    }*/

private:

    AA()
    {}
    int _a;
};


class BB :public AA
{
protected:
    int _b;
};

int main()
{
    BB bb;

    system("pause");
    return 0;
}

这里写图片描述


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

思路:

沿用上一题的思路,将拷贝构造定义成私有成员,只提供创建对象在堆上的接口

代码一:

class AA
{
public:
    static AA* GetObject()
    {
        return new AA;
    }

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

分析:上面代码可以实现将对象创建在堆上,但不可避免的是创建的对象也可以在栈上;拷贝构造不是私有成员,当我们利用拷贝构造时,就可将对象创建在栈上,例如:

    AA* aa=AA::GetObject();
    AA aa1(*aa);//利用拷贝构造出来的对象在栈上
    AA aa2 = *aa;
    system("pause");
    return 0;

解决办法:

既然会利用拷贝构造创建出在栈上的对象,因此我们可对拷贝构造作两件事情,并且二者缺一不可:

  1. 将拷贝构造定义成私有成员

  2. 只声明拷贝构造,但不实现拷贝构造

关于上述的两个条件,通过下面代码来验证:

代码1:公有成员,只声明拷贝构造,但不实现拷贝构造

class AA
{
public:
    static AA* GetObject()
    {
        return new AA;
    }

    AA(const AA& aa);
private:
    AA()
    {}
    int _a;
};

AA::AA(const AA& aa)
{
    cout << "AA(const AA& aa)" << endl;
}
int main()
{
    AA* aa=AA::GetObject();
    AA aa1(*aa);//利用拷贝构造出来的对象在栈上
    AA aa2 = *aa;
    system("pause");
    return 0;

}

结果分析:虽然在类里没有实现拷贝构造,但突破类域,我们依然可以实现,此时调用拷贝构造,创建的对象依旧在栈上

这里写图片描述

代码2:只声明不实现的拷贝构造为私有成员

class AA
{
public:
    static AA* GetObject()
    {
        return new AA;
    }   
private:
    AA()
    {}
    AA(const AA& aa);
    AA& operator=(const AA& aa);
    int _a;
};

int main()
{
    AA* aa=AA::GetObject();
    AA aa1(*aa);//利用拷贝构造出来的对象在栈上
    AA aa2 = *aa;
    system("pause");
    return 0;

}

结果分析:将拷贝构造声明为私有成员,并且不实现,此时在类外面调不动私有成员,只能通过创建对象接口来构造对象,并且构造的对象的堆上

这里写图片描述


3. 实现一个类,创建的对象只能在栈上

思路:

和上题的思路一样,将构造封装成私有成员,提供构造对象的接口

代码:

class AA
{
public:
    static AA GetObject()
    {
        return AA();
    }
private:
    int _a;
};


int main()
{
    AA aa = AA::GetObject();

    system("pause");
    return 0;
}

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

思路:

在堆上定义对象,无非是通过new和delete来完成,故此我们将new和delete两个操作符都封装成私有成员,并且不实现,即可达到目的

代码:

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

int main()
{
    AA aa;
    AA* p = new AA;

    system("pause");
    return 0;
}

结果:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/zhangye3017/article/details/80053266