我正在尝试编写一个必须检查正确初始化的cpp模块。它需要使用至少一个非NULL指针进行初始化。如果没有,它需要删除自己并返回NULL。以下程序似乎确实破坏了对象,但它似乎没有返回null。
这里发生了什么?
#include <iostream>
using namespace std;
class cmod {
public:
cmod(int *p1=NULL, int *p2=NULL)
{
if( p1 == NULL && p2 == NULL){
delete(this);
}
else
cout << __func__ << ": Initialized" << endl;
if(p1 != NULL)
cout << "*p1 = " << *p1 << endl;
if(p2 !=NULL)
cout << "*p2 = " << *p2 << endl;
}
~cmod()
{
cout << __func__ << ": Destroyed" << endl;
}
};
int main()
{
int a=10, b = 20;
cmod *p = new cmod();
if(p == NULL)
cout << __func__ << ": Unable to initialize" << endl;
cmod *p1 = new cmod(&a, &b);
}
以下是输出:
~cmod: Destroyed
cmod: Initialized
*p1 = 10
*p2 = 2
为什么行Unable to initialize
无法打印?
更新: 在查看了所有答案之后,我想出了以下内容:
#include <iostream>
using namespace std;
class cmod {
private:
int *l1,*l2;
cmod()
{
throw std::runtime_error("Failed to construct object. No arguements");
}
cmod(int *p1=NULL, int *p2=NULL)
{
if( p1 == NULL && p2 == NULL){
throw std::runtime_error("Failed to construct object. Both args NULL");
}
else
cout << __func__ << ": Initialized" << endl;
if(p1 != NULL)
l1 = p1;
if(p2 !=NULL)
l2 = p2;
}
~cmod()
{
cout << __func__ << ": Destroyed" << endl;
}
public:
static cmod * initialize(int *p1=NULL, int *p2 = NULL)
{
if( p1 == NULL && p2 == NULL){
return NULL;
}
else
return new cmod(p1,p2);
}
void dump()
{
cout << __func__ << ": a = " << *l1 << endl;
cout << __func__ << ": b = " << *l2 << endl;
}
int main()
{
int a=10, b = 20;
cmod *p = cmod::initialize(NULL, NULL);
if(p == NULL)
cout << __func__ << ": Unable to initialize" << endl;
cmod *p1 = cmod::initialize(&a, &b);
if(p!=NULL)
p->dump();
if(p1!=NULL)
p1->dump();
}
现在这是一种正确的方法吗?
答案 0 :(得分:10)
构造函数将始终返回其类的对象,除非它抛出异常。所以你要做的就是这样:
cmod(int *p1=NULL, int *p2=NULL)
{
if( p1 == NULL && p2 == NULL)
throw std::runtime_error("Failed to construct object.");
}
答案 1 :(得分:3)
你不能delete this
。考虑以下情况中会发生什么:
cmod A; // default constructor: called with both arguments NULL
当A
没有在堆上分配,但生活在堆栈上时。但是使用未由delete
分配的指针调用new
是一个错误的程序(如果你很幸运它会在运行时崩溃)。
正如Harald所指出的,处理构造函数输入错误的适当且正确的方法是抛出异常。使用工厂并不完全合适,因为用户仍可能尝试通过其他方式构建对象(除非通过使工厂成为friend
和构造函数private
或protected
来禁止)
答案 2 :(得分:3)
如果要在构造对象之前验证输入,最好使用static
成员函数来执行此操作,而不是验证构造函数中的输入。另外,使构造函数private
防止意外误用。
class cmod {
public:
static cmod* buildInstance(int *p1=NULL, int *p2=NULL)
{
if( p1 == NULL && p2 == NULL){
return NULL;
}
else {
return new cmd(p1, p2);
}
}
~cmod()
{
cout << __func__ << ": Destroyed" << endl;
}
private:
cmod(int *p1, int *p2)
{
cout << __func__ << ": Initialized" << endl;
if(p1 != NULL)
cout << "*p1 = " << *p1 << endl;
if(p2 !=NULL)
cout << "*p2 = " << *p2 << endl;
}
};
然后将其用作:
int main()
{
int a=10, b = 20;
cmod *p = mod::buildInstance();
if(p == NULL)
cout << __func__ << ": Unable to initialize" << endl;
cmod *p1 = cmod::buildInstance(&a, &b);
}
答案 3 :(得分:2)
您需要使用工厂模式来创建对象,以便将对象创建委派给工厂。这样工厂可以控制是否应该创建对象。
所以创建另一个名为cmodFactory的类,它有一个返回cmod的静态方法。在此静态方法中,您可以检查是否要创建对象并相应地返回。
添加示例代码:
#include <iostream>
using namespace std;
class cmod {
public:
cmod(int *p1=NULL, int *p2=NULL)
{
cout << __func__ << ": Initialized" << endl;
if(p1 != NULL)
cout << "*p1 = " << *p1 << endl;
if(p2 !=NULL)
cout << "*p2 = " << *p2 << endl;
}
~cmod()
{
cout << __func__ << ": Destroyed" << endl;
}
};
class cmodFactory {
public:
static cmod * getCmodInstance(int *p1=NULL, int *p2=NULL)
{
if( p1 == NULL && p2 == NULL){
return NULL;
}
else
{
cmod * instance = new cmod(p1, p2);
return instance;
}
}
};
int main()
{
int a=10, b = 20;
cmod *p = cmodFactory::getCmodInstance();
if(p == NULL)
cout << __func__ << ": Unable to initialize" << endl;
p = cmodFactory::getCmodInstance(&a, &b);
if(p == NULL)
cout << __func__ << ": Unable to initialize" << endl;
else
cout << __func__ << ": initialized" << endl;
}
输出
main: Unable to initialize
cmod: Initialized
*p1 = 10
*p2 = 20
main: initialized
答案 4 :(得分:1)
构造函数不能返回null。构造函数不返回指针。在构造函数中调用delete(this)
是各种错误的。
有一种方法可以取消对象的构造:抛出异常。在那种情况下,new-expression不会返回null。事实上,它根本没有回归。相反,你必须捕获异常来处理这种情况。
为什么&#34;无法初始化不打印?
因为除非使用非抛出变量并且分配(与对象的初始化分开)失败,因此新表达式永远不会返回null。在这种情况下,分配没有失败,并且使用了抛出变体(默认值)。