有没有办法用类实例指针调用构造函数?

时间:2011-04-27 15:07:00

标签: c++

我们可以通过类指针显式调用析构函数,为什么不构造函数?有什么想法吗?

#include <iostream>

class Con {
public:
    Con( int x ) : x( x ) {

    }

private:
    int x;
};

int main() {
    Con* c = new Con( 1 );
    //c->Con( 2 ); //illegal
    c->~Con(); // ok!
    delete c;
}

谢谢,

8 个答案:

答案 0 :(得分:18)

你实际上可以调用它,只是语法不是调用成员方法的语法(析构函数是特殊情况),所以不能使用成员访问运营商。相反,您必须使用 placement-new 语法:

Con c;
c.~Con();        // destroy, now c is not a Con anymore
new (&c) Con();  // recreate, now c is a Con again

作为特殊情况,在C ++ 0x提议中,实际上在其中一个代码示例中使用,提供了在包含非的联合的情况下将union重用为不同类型的方法POD元素:

union U {
   int i;
   float f;
   std::string s;
};

int main() {
   U u;
   new (&u.s) std::string( "foo" );
   u.s.~string();
   u.i = 5;
}

}

答案 1 :(得分:12)

没有。你不能。

Con* c = new Con( 1 );
//c->Con( 2 ); //illegal

您已经在new表达式中调用了构造函数。

当你有一个Con*类型的有效指针时,你已经创建了一个对象。在“构造”对象上调用构造函数甚至没有意义。那么C ++为什么会允许呢?

答案 2 :(得分:2)

如果您不将构造函数和析构函数视为您调用的函数,那么对您来说会更容易。你不打电话给他们。您只能构造或销毁对象。而且,作为构造的一部分,构造函数体被执行。同样,作为对象破坏的一部分,执行析构函数体。

所以你可以在堆栈上构造对象

YourClass variable(constructor_arguments);

当它超出范围时会被自动销毁。

您还可以在堆上创建对象

YourClass * ptr = new YourClass(parameters);

要破坏此类对象,请使用运算符delete

delete ptr;

您还可以在自己提供的某些内存中构建一个对象(很少需要)

char * pool = new char[sizeof(YourClass)]
YourClass *ptr = new(pool) YourClass(parameters);

你明确地破坏了这样一个对象,语法看起来像函数invokation,但它更像是一个对象破坏

ptr->~YourClass();

在此行之后,您的对象不再存在。在其上调用任何内容是一种未定义的行为。而且您仍然需要管理为此对象分配的内存

delete[] pool;

所以,你的问题意味着'为什么我能明确地破坏一个我有指针但我无法构造它的对象'?你不能,因为它已经构建好了。

您还可以阅读C++ FAQ Lite explanation

答案 3 :(得分:0)

不,你不能按照你解释的方式调用类的构造函数,那是因为,c没有指向con类型的有效对象。

答案 4 :(得分:0)

您只能在对象构造时调用构造函数,因此它的名称。一旦构造了对象,我就没有理由为什么你想在同一个对象上再次调用它。如果你想做某事,你需要调用该类中定义的函数。

答案 5 :(得分:0)

构造函数的意图是在创建对象时调用。没有其他的。如果你有一个引用计数器来跟踪对象的数量,允许将构造函数作为函数调用会使计数器崩溃。

如果要重新初始化或重置对象,可以添加一个名为Reset()或Initialize()的函数,并从构造函数中调用它。然后,您还可以从对象指针调用Reset()或Initialize()。

答案 6 :(得分:0)

还有一种方法:

template <typename T, typename... Args>
using fn_ExternFunctionConstructorType = void(__thiscall T::*)(Args...);

template <typename RetType, typename T, typename... Args>
using fn_ExternFunctionType = RetType(__thiscall T::*)(Args...);

class __declspec(dllexport) CTest
{
public:
    CTest()
    {
        std::cout << 6 << std::endl;
    }
    int bla(int val) { std::cout << val << std::endl; return -1; }
};


int main(int argc, char** argv)
{
    FARPROC pFuncConstructor = GetProcAddress(GetModuleHandle(NULL), "??0CTest@@QAE@XZ");
    FARPROC pFuncBla = GetProcAddress(GetModuleHandle(NULL), "?bla@CTest@@QAEHH@Z");
    CTest* pTest = (CTest*)malloc(sizeof(CTest));
    (pTest->*reinterpret_cast<fn_ExternFunctionConstructorType<CTest>&>(pFuncConstructor))();
    (pTest->*reinterpret_cast<fn_ExternFunctionType<int, CTest, int>&>(pFuncBla))(99);
    return 0;
}

编辑:接第二个构造函数调用

答案 7 :(得分:0)

Ofc你可以从对象实例中调用它,请参阅以下代码:

 #include <iostream>
class foo{
      public :
      int foo_var;
      foo(){
            std::cout<<"foo_var = "<<foo_var<<std::endl;
            }
      };
int main()
{
    foo * f = new foo();
    // set foo_var
    f->foo_var = 10;
    // call constructor by passing object instanse
    foo * f1 = new(f) foo;
    std::cout<<(f==f1)<<std::endl;
    system("pause");
    return 0;
}

第二个输出是“foo_var = 10”,所以它正在工作。第三个输出是“true”然后(f == f1),这意味着构造函数不分配新的内存(运算符new,但我们传递一个指针,所以他不会分配另一个) 你真的很有用:

#include <iostream>
template <class t>
class smart_pointer{
      t * p; // the real normal pointer
      public :
      smart_pointer()
      {
          p = (t*) malloc(sizeof(t)); // allocate memory 
          try{ 
          new (p) t; // call the constructor 
          } catch (...)  // if it throws any exception
          {
                  free(p); // free p , dont use delete , because it will
                  // call the destroctor calling the destructor will cause 
                  // freeing a not allocated memory that causes a crash
                  throw; // throw the exception what ever it was
          }

      }
      ~smart_pointer(){delete p;}
      t operator = (t val) // assigment operator
      {
               *p = val;
               return val;
      }
      operator t(){ // type casting operator , usually for std::cout
               return *p;
               }
      };
int main()
{
    smart_pointer<int> x;
    x = 10;
    std::cout<<x<<std::endl;
    system("pause");
    return 0;
}

建议阅读“有效的c ++”,“更有效的c ++”,“有效的现代c ++”书籍