如何在构造函数中销毁对象并返回NULL

时间:2017-01-30 18:16:39

标签: c++ pointers

我正在尝试编写一个必须检查正确初始化的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();
}

现在这是一种正确的方法吗?

5 个答案:

答案 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和构造函数privateprotected来禁止)

答案 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。在这种情况下,分配没有失败,并且使用了抛出变体(默认值)。