静态建立对象
编译器为对象在栈空间中分配内存,直接挪动栈顶指针,腾出适当的空间,来构造对象
动态建立对象分为两步
1.使用 operator new 函数,在堆上找合适的内存进行分配
2.调用构造函数构造对象,初始化这块空间
一.只能在堆上生成对象的类
首先,要实现一个只能在堆上生成的类,应该断绝一切构造的源头
1.构造函数
2.拷贝构造函数
3.赋值运算符的重载
断绝这三个函数的方法
● 将这三个函数都声明为私有的 -> 防止在类外被重新定义
● 在类内部只声明,不定义 -> 不让系统产生默认的构造函数
其次,为了可以生成对象,我们应该给出一个函数专门用来在堆上构造对象
1.首先这个函数必须是静态的 -> 如果是非静态的,我们就必须用对象的this指针来调用,现在我们的构造函数时私有的,所以根本没有办法构造出对象,也就无法产生this指针来调用成员函数,但是静态的成员函数不需要this指针的调用,所以这里我们使用静态的成员函数来构造对象.
2.这个函数必须是公有的 -> 因为我们要在类外面构造对象,需要调用这个函数,所以这个函数的访问限定符一定是公有的
代码如下:
class AA
{
public:
static AA* GetAA(int a)
{
return new AA(a);
}
void destoryAA()
{
delete this;
}
private:
//类的防拷贝
// 1.只声明不定义
// 2.声明为私有的,防止在类外被定义
AA(int a = 0):_a(a){}
AA(const AA& a){}
AA& operator=(const AA& a){}
int _a;
};
int main()
{
AA* a = AA::GetAA(2);
a->destoryAA();
return 0;
}
二.只能在栈上生成对象的类
上面说了在堆上建立对象,得经过 operator new + 构造函数两步
方法一 . 我们可以让对象调不到 operator new 函数,那自然也就不能通过堆来生成对象的
class AA
{
private:
void* operator new(size_t size);
void operator delete(void* p);
};
在我们没有重载operator new 和 operator delete时,编译器会调用系统默认的这两个函数
为了达到我们只能在栈上构造对象的要求,我们只有自己重载这两个函数,这样编译器知道我们自己写了,就不会再去调用系统的了
又由于我们这两个函数是私有的,外部根本调不到,也防止了在类外面定义,也就达到了我们的目的
!!!!!但是,这个方法有一个缺陷,就是,他虽然防止了在堆上生成对象,但是,他可以在全局区上生成对象.
方法二 . 还是修改构造函数,来使对象只能生成在栈上
class AA
{
public:
static AA GetAA(int a)
{
return AA(a);
}
private:
AA(int a) :_a(a){}
int _a;
};
int main()
{
AA a = AA::GetAA(2);
return 0;
}
上面的方法可以使我们不管在函数外还是函数内都在栈上生成对象
注 : 以上代码将成员函数声明为私有的,就不可以被继承,为了便于继承,我们可以将私有改为保护