[英]How do you destroy an object in its constructor and return NULL
我正在嘗試編寫一個必須檢查正確初始化的 cpp 模塊。 它需要用至少一個非空指針初始化。 如果不是,它需要刪除自己並返回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();
}
現在這是一個正確的方法嗎?
構造函數將始終返回其類的對象,除非它拋出異常。 所以你想要做的是:
cmod(int *p1=NULL, int *p2=NULL)
{
if( p1 == NULL && p2 == NULL)
throw std::runtime_error("Failed to construct object.");
}
你不能delete this
。 考慮在以下場景中會發生什么:
cmod A; // default constructor: called with both arguments NULL
當A
不在堆上分配,而是在堆棧上時。 但是用一個不是由new
分配的指針調用delete
是一個錯誤的程序(如果你幸運的話它會在運行時崩潰)。
正如 Harald 指出的那樣,處理構造函數的錯誤輸入的適當且正確的方法是 throw 和 exception 。 使用工廠並不完全合適,因為用戶可能仍會嘗試通過其他方式構造對象(除非通過將工廠設為friend
並且將構造函數設為private
或protected
來禁止這樣做)。
如果要在構造對象之前驗證輸入,最好使用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);
}
您需要使用工廠模式來創建對象,以便將對象創建委托給工廠。 通過這種方式工廠可以控制是否應該創建對象。
所以創建另一個名為 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
構造函數不能返回 null。 構造函數不返回指針。 在構造函數中調用delete(this)
是各種錯誤。
有一種方法可以取消對象的構造:拋出異常。 但是,在這種情況下,新表達式不會返回 null。 事實上,它根本不會返回。 相反,您必須捕獲異常才能處理這種情況。
為什么“無法初始化不打印?
因為除非使用非拋出變量並且分配(與對象的初始化分開)失敗,否則 new 表達式永遠不會返回 null。 在這種情況下,分配沒有失敗,並且使用了拋出變量(默認)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.