有没有办法用类实例指针调用构造函数?
我们可以通过类指针显式调用析构函数,为什么不是构造函数?任何想法?有没有办法用类实例指针调用构造函数?
#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;
}
感谢,
号你不能。
Con* c = new Con(1);
//c->Con(2); //illegal
您已经在new
表达式中调用构造函数。
当你有一个Con*
类型的有效指针时,你已经创建了一个对象。并且在“构造”对象上调用构造函数甚至没有意义。那么为什么C++会允许这样做呢?
不,你不能以你解释的方式调用类的构造函数,那是因为c没有指向con类型的有效对象。
只有当对象被构造为时,才能调用构造函数,因此它是名称。一旦对象被构建,我看不到为什么你想再次在同一个对象上调用它。如果你想做一些事情,那么你需要调用该类中定义的函数。
实际上,你可以调用构造函数,而不是使用成员访问语义,而是使用* placement-new *(void *'版本的全新目的new *提供了创建方法*一个对象就位,即在内存块上执行构造函数) – 2011-04-27 16:03:03
@David,thx!我还没有先进到已经知道,但:) – 2011-04-27 16:04:29
构造函数的意图是在创建对象时调用。没有其他的。如果你有一个引用计数器来跟踪对象的数量,允许将构造函数作为函数调用会使计数器变得混乱。
如果要重新初始化或重置对象,可以添加名为Reset()或Initialize()的函数,并从构造函数中调用它。然后,您也可以从对象指针调用Reset()或Initialize()。
如果您不认为构造函数和析构函数是函数,那么调用它会更容易。你不要给他们打电话。你只能构造或破坏一个物体。并且,作为构造的一部分,构造函数体被执行。同样,作为对象销毁的一部分,析构函数体被执行。
所以你可以在栈
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
实际上,你可以调用它,它只是语法不是调用成员方法(其中的析构函数是一个特殊的情况下),所以它不与完成会员访问运营商。相反,你必须求助于投放新语法:
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;
}
}
还有一种方法:
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;
}
编辑:采取了第二个构造函数调用了
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++” 的书籍
'C->〜CON();'可能是好的,但'删除c;'在下一行不是,因为它会试图再次调用同一个析构函数。 – Cubbi 2011-04-27 15:11:18
您正在通过_object pointer_调用析构函数。不是类指针。 – xtofl 2011-04-27 15:12:32
由于xtofl上面说过,您正在使用对象指针调用析构函数。但是如果你没有使用构造函数,你就没有指向构造函数的对象。 – Sam 2011-04-27 15:18:52