2011-04-27 58 views
10

我们可以通过类指针显式调用析构函数,为什么不是构造函数?任何想法?有没有办法用类实例指针调用构造函数?

#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; 
} 

感谢,

+0

'C->〜CON();'可能是好的,但'删除c;'在下一行不是,因为它会试图再次调用同一个析构函数。 – Cubbi 2011-04-27 15:11:18

+1

您正在通过_object pointer_调用析构函数。不是类指针。 – xtofl 2011-04-27 15:12:32

+0

由于xtofl上面说过,您正在使用对象指针调用析构函数。但是如果你没有使用构造函数,你就没有指向构造函数的对象。 – Sam 2011-04-27 15:18:52

回答

10

号你不能。

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

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

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

+1

谢谢,很好的解释。 – Chan 2011-04-27 15:28:00

+1

这可能不错,但它不正确:不是你不能调用构造函数,而是执行构造函数的语法是特殊的* placement-new *:'new(c)Con(1);' 。 – 2011-04-27 16:00:40

+0

@大卫:什么是不对的?您不要在对象上调用构造函数。您正在“构建”另一个对象,它位于当前由'c'占据的相同内存中。这与“新”表达式本身没有多大区别。 – Nawaz 2011-04-27 16:04:53

0

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

0

只有当对象被构造为时,才能调用构造函数,因此它是名称。一旦对象被构建,我看不到为什么你想再次在同一个对象上调用它。如果你想做一些事情,那么你需要调用该类中定义的函数。

+0

实际上,你可以调用构造函数,而不是使用成员访问语义,而是使用* placement-new *(void *'版本的全新目的new *提供了创建方法*一个对象就位,即在内存块上执行构造函数) – 2011-04-27 16:03:03

+0

@David,thx!我还没有先进到已经知道,但:) – 2011-04-27 16:04:29

0

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

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

1

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

所以你可以在栈

YourClass variable(constructor_arguments); 

上构建对象,当它超出范围就会被自动销毁。

您也可以在堆上创建对象

要破坏你使用运营商这样一个对象delete

delete ptr; 

你也可以构造一个对象在你自己提供的一些内存(很少需要)

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

你破坏了这样一个对象explic itely和语法类似于函数invokation,但它是相当的物件破坏

ptr->~YourClass(); 

这一行你的对象是没有更多的经过。调用任何东西都是未定义的行为。而且你还必须管理你为这个对象

delete[] pool; 

所以分配的内存,你的问题的意思是“我为什么可以明确地破坏一个对象,我有一个指针,但我不能建造它?你不能,因为它已经建成。

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

15

实际上,你可以调用它,它只是语法不是调用成员方法(其中的析构函数是一个特殊的情况下),所以它不与完成会员访问运营商。相反,你必须求助于投放新语法:

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; 
} 

}

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), "[email protected]@[email protected]"); 
    FARPROC pFuncBla = GetProcAddress(GetModuleHandle(NULL), "[email protected]@@[email protected]"); 
    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; 
} 

编辑:采取了第二个构造函数调用了

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”,所以它是工作。第三个输出是“真”,然后(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++” 的书籍

相关问题