C++的类中有什么方法做到依据构造函数参数终止类的创建

永夜星空 2010-12-08 12:54:02
如有这么一个类:

class C
{
int xx,yy;
public:
C(int x,int y)
{
if(xx,yy为合格参数)
{
xx=x;
yy=y;
}
else
{
... //终止此次实例的创建,并使调用者获得一个NULL指针
}
}
~C(){};
};

int main()
{
C* p=new C(3,4); //我期望如果参数不合格则p=NULL;
if(p)
{
...
}
}

希望在类的构造函数中实现这么个功能。
我试过在构造函数中使用语句:
delete this;
但是这样的话上层的调用代码无法知道类实例到底有没有创建成功(即上面main函数中p=new C(3,4))的p的值不受自己指定。
还试了下重载new操作符,虽然可以使p的值为NULL,但是如果p的值为NULL则根本就不会再执行构造函数了,函数new的执行是在构造函数之前的。如果构造函数能和重载的new互动就好了,可是new是静态成员。

如果有许多些复杂的参数,那么要在调用new之前调用太多的判断,有点麻烦。
我以前的做法就是在类中设置了一个标志,指示实例的创建是否合格,但是这样还是要在类的外部调用delete删除不合格的实例。

其实我就是有个简朴的期望:类写的复杂一点无所谓,关键是使用类的地方代码要清爽。
我弄来弄去都实现不了这样一个类,也不知道是不是C++不可实现这样的要求,但我觉得我的想法很合理。
...全文
259 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq120848369 2010-12-08
  • 打赏
  • 举报
回复
catch里什么都不做,然后系统就会delete那块内存么,如果构造函数中途又开辟了其他内存,然后异常了,即便捕获了也没有用.
bluewanderer 2010-12-08
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 qq120848369 的回复:]
你也懂的,正如gules所说,构造函数里抛出异常,内存已经泄漏了,比较好的做法就是加个工厂类来提前对参数做异常处理之后再new对象返回,或者直接给你的类加一个static函数先处理异常,再new对象给用户,并且把构造函数先私有化,避免栈对象与自己new对象这些情况的出现.
[/Quote]

构造函数抛异常会自动delete,本身这是个解决方案,只是写出来不怎么舒坦而已。

A *a;

try
{
a = new A(1, 2, 3);
}
cathc (...)
{
}

----

void foo()
{
A a(1, 2, 3);
}

try
{
foo();
}
catch (...)
{
}
qq120848369 2010-12-08
  • 打赏
  • 举报
回复
你也懂的,正如gules所说,构造函数里抛出异常,内存已经泄漏了,比较好的做法就是加个工厂类来提前对参数做异常处理之后再new对象返回,或者直接给你的类加一个static函数先处理异常,再new对象给用户,并且把构造函数先私有化,避免栈对象与自己new对象这些情况的出现.
LB065X 2010-12-08
  • 打赏
  • 举报
回复
额,不是很懂,
luciferisnotsatan 2010-12-08
  • 打赏
  • 举报
回复
lz看下 设计模式 这本书吧。对编程很有好处的
luciferisnotsatan 2010-12-08
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 liuhua1982 的回复:]

工厂模式似乎是COM的内容,我平时就做一些小软件的开发,所以一直以来都回避了COM。熟悉COM似乎不是一时半会的事情,既然大家都说要这么做看样子还是先修炼好COM再来解决这个问题吧。
[/Quote]
工厂模式是中设计模式。
是COM里有用到工厂模式,而不是工厂模式是COM的内容
ww884203 2010-12-08
  • 打赏
  • 举报
回复
学习了,楼上的都说得很好
gules 2010-12-08
  • 打赏
  • 举报
回复
单纯想在构造函数中完成此事,不可能,原因有两点:
1、如果你定义的对象是自动对象(或栈对象)呢,即写 C c; 这样的代码,哪来指针?
2、构造函数是被系统(编译系统)自动扩展调用的,被调用时内存已分配完毕!即
C* p = new C; 这样的代码返回指针的不是构造函数,而是operator new函数。
bluewanderer 2010-12-08
  • 打赏
  • 举报
回复
工厂模式不是COM的内容。不过主要目的是为了处理创建时候的类型多态问题。比如A有一大堆子类,然后A有一个Create之类的函数会根据传进去的参数建立某个对应的子类的对象。

比如假设有Connection类如果你Connection::Create("http://...")就给你反回一个HttpConnection 你写"ftp://..."就给你反回一个FtpConnection

回避new判断错误只能通过异常最直接的方法就是 把可能出异常的构造部分单独放一个函数。

A *a = new a();

if (!a->init(xx, yy))
{
delete a;

// 其他错误处理
}
永夜星空 2010-12-08
  • 打赏
  • 举报
回复
工厂模式似乎是COM的内容,我平时就做一些小软件的开发,所以一直以来都回避了COM。熟悉COM似乎不是一时半会的事情,既然大家都说要这么做看样子还是先修炼好COM再来解决这个问题吧。
jxguo_05 2010-12-08
  • 打赏
  • 举报
回复
auto_ptr就是用的类似机制,封装指针到类里,构造异常或是退出类的作用域后自动析构
jxguo_05 2010-12-08
  • 打赏
  • 举报
回复
最直接的就在构造函数里,随便throw一个异常,此时它就会自动rollback,对象不会创建
dxms8 2010-12-08
  • 打赏
  • 举报
回复
恩,工厂模式好用~
qq120848369 2010-12-08
  • 打赏
  • 举报
回复
的确,再加一个类是很和谐的。
ryfdizuo 2010-12-08
  • 打赏
  • 举报
回复
工长模式只是创建对象,不管理对象的生命周期~
luciferisnotsatan 2010-12-08
  • 打赏
  • 举报
回复
做成工厂模式吧。
弄个create函数,根据参数创建类对象,然后返回该对象
wyget 2010-12-08
  • 打赏
  • 举报
回复
再定义一个控制类C的类
class CControl
{
public:
CControl()
{
if (符合条件)
pC = new C();
else
pC = NULL;
}
private:
C* pC;
}
jixingzhong 2010-12-08
  • 打赏
  • 举报
回复
参考工厂模式
永夜星空 2010-12-08
  • 打赏
  • 举报
回复
看了各位的解析我对一些脚本语言中的CreateObject函数也有了新的认识,比如说VBS中我原来一直以为CreateObject与C++中的new是等同的,原来还有这么多道道。

另外我觉得使用异常处理机制来处理我的问题打心里有点不情愿(事实上我没有使用异常处理的习惯,也不熟悉它,而且总觉得异常处理是用来对付像内存不足等问题的)。鉴于造个新类来处理对象的创建的复杂性(至少过段时间再复习曾经的代码就要理很久,而且我只是写些小软件),我采用了qq120848369的建议。下面是我写的测试代码:

class A
{
private:
int xx,yy;
A(int x,int y){xx=x;yy=y;}; //声明为私有的,杜绝通过CreateObject以外途径创建实例
~A(){};
bool IsValidate() //这个函数用来判断参数是合格的
{
//....
};
public:
static A* CreateObject(int x,int y) //声明为静态成员
{
A* p=new A(x,y);
if(!p)return 0;
if(p->IsValidate())return p;
delete p;
return 0;
}
void Release()
{
delete this;
}
public:
void Show()
{
printf("%d,%d\n",xx,yy);
}
};

int _tmain(int argc, _TCHAR* argv[])
{
for(int i=0;i<0xFFFFFFFF;i++) //循环几亿次看看会不会泄露等错误
{
A* pa=A::CreateObject(4,4);
if(pa)
{
//pa->Show();
pa->Release();
}
}
return 0;
}

bluewanderer 2010-12-08
  • 打赏
  • 举报
回复
当然我个人也不建议依赖这个机制,不符合个人审美。只是说有这个机制而已。
加载更多回复(2)

64,639

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧