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;
};