定义一个只能在栈上构造对象的类

只能在堆上定义的对象可以通过声明构造函数是私有的,然后提供两个静态的方法,一个方法用来获取堆上的对象,一个用来释放堆上的对象。C++中定义一个不能被继承的类中第二种方法就是通过这种方式声明了一个不能被继承的类,但是这个类的对象就只能位于堆中了。


那么如何一定一个只能在栈上构造的对象?

这个就涉及到了C++中new这个操作符,它包含两步:

  1. 调用一个全局的operator new函数分配一定的内存空间
  2. 调用对象的构造函数

如果不允许一个类在堆上分配内存,但是允许其在栈上分配内存,对比这两种方式可以发现只需要禁止第一步的操作即可,就是禁止一个对象调用operator new函数。这可能就涉及到了operator new这个库函数了,对于类,这个库函数是可以被重载的,只需要将它重载成私有的即可。这是C++ reference中对operator new的说明。可以查看这个链接中对operator new的说明即可。下面的函数原型就是从上面的文档中拷贝过来的。这里甚至可以不写实现。

#include <iostream>
#include <new>

using namespace std;


class A
{
		public:
				A()
				{
					cout<<"a con"<<endl;
				}

				~A()
				{
					cout<<"a des"<<endl;
				}
		private:
				static void* operator new (std::size_t size) throw (std::bad_alloc);
				static void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw();
				static void* operator new (std::size_t size, void* ptr) throw();
		
};
int main()
{
	A a;
	A * ap=new A();
	return 0;
}

可以发现输出提示错误:


如果把main函数中第二行代码去掉,函数是可以正常运行的:

即表示它可以在栈上构造对象。


同时在看上面new的过程中发现了new其实可以使用栈上的内存来构造对象。就是使用placement new这个版本,如果提供给new一个栈上的地址,它会在栈上构造对象。注意使用placement new这个版本时需要显示调用析构函数。

#include <iostream>

using namespace std;

class A
{
		public:
			A(int t=1)
			{
				d=t;
				cout<<d<<"a con"<<endl;
			}
			int d;
			~A()
			{
				cout<<d<<"a des"<<endl;
			}
			

};
int main()
{
	const int Len=sizeof(A);
	char buf[Len];	
	A * a=new(buf) A(2);//调用placement new这个版本
	a->~A();//注意这里需要显示调用析构函数,因为buf中的内存是在栈中的,所以函数跳出后内存会被释放
	return 0;
}

执行输出:




### 定义实现数据结构的 为了在 Java 中定义一个,可以创建名为 `MyStack` 的来封装的操作。此应支持基本操作如压 (`push`)、弹 (`pop`) 和查看顶元素 (`peek`) 等功能。 #### MyStack 的设计 该内部维护一个数组用于存储中的元素,并通过两个变量管理的状态: - `arr`: 存储内元素的实际容器。 - `top`: 记录当前顶位置;初始化为 `-1` 表示空状态。 - `maxSize`: 数组的最大容量,默认初始大小可以根据需求设定。 当执行 `push` 方法时,先检查是否已满,对于动态数组而言不需要手动处理扩容逻辑,因为 Java 集合框架下的 ArrayList 已经实现了自动增长机制[^3]。然而,在这里假设采用固定长度数组,则需显式地进行边界检测与扩展工作。 下面是具体的代码实现方式: ```java public class MyStack { private int[] arr; private int top = -1; private int maxSize; // 构造函数初始化对象及其属性 public MyStack(int size) { this.maxSize = size; this.arr = new int[size]; } // 压入新元素至顶 public void push(int data) { if (isFull()) { resizeArray(); } arr[++top] = data; } // 移除并返回顶元素 public Integer pop() { if (isEmpty()) { System.out.println("The stack is empty."); return null; } return arr[top--]; } // 查看而不移除顶元素 public Integer peek() { if (!isEmpty()) return arr[top]; else { System.out.println("The stack is empty."); return null; } } // 判断是否为空 public boolean isEmpty() { return top == -1; } // 检查是否达到最大容量 private boolean isFull() { return top >= maxSize - 1; } // 动态调整数组尺寸以适应更多元素加入 private void resizeArray() { int newSize = maxSize * 2; arr = java.util.Arrays.copyOf(arr, newSize); maxSize = newSize; } // 输出整个的内容供调试使用 public void print() { if (isEmpty()){ System.out.println("已空,无法输出"); return; } for (int i = top; i >= 0; i--) { System.out.println("stack[" + i + "] = " + arr[i]); } } } ``` 此段代码展示了如何构建一个简单的基于数组的,其中包含了必要的成员方法以及辅助性的私有方法来进行的基本操作和自我管理[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值