C++ 为什么我不能叫我的班';从C++;?

C++ 为什么我不能叫我的班';从C++;?,c++,constructor,destructor,C++,Constructor,Destructor,什么时候类的对象可以调用该类的析构函数,就好像它是一个常规函数一样?为什么它不能调用同一类的构造函数,作为它的常规函数之一?为什么编译器阻止我们这样做 例如: class c { public: void add() ; c(); ~c() ; }; void main() { c objC ; objC.add() ; objC.~c() ; // this line compiles objC.c() ; // compilation error } 必须在

什么时候类的对象可以调用该类的析构函数,就好像它是一个常规函数一样?为什么它不能调用同一类的构造函数,作为它的常规函数之一?为什么编译器阻止我们这样做

例如:

class c
{
public:
   void add() ;
   c();
   ~c() ;
};

void main()
{
 c objC  ;
 objC.add() ;
 objC.~c() ; // this line compiles
 objC.c() ;  // compilation error
}

必须在类的现有实例上调用析构函数-它所做的就是销毁实例。构造函数创建一个全新的类实例,因此调用现有实例毫无意义

这与新建和删除工作的方式类似:

int * p = new int;    // call to new needs no existing instance
delete p;             // call to delete requires existing instance

请注意,在您的代码中,对象将被销毁两次,一次是显式销毁,一次是隐式销毁。通常,只有在执行异常操作(可能涉及使用placement new)时,才显式调用析构函数。

必须在类的现有实例上调用析构函数-销毁实例就是它所做的。构造函数创建一个全新的类实例,因此调用现有实例毫无意义

这与新建和删除工作的方式类似:

int * p = new int;    // call to new needs no existing instance
delete p;             // call to delete requires existing instance

请注意,在您的代码中,对象将被销毁两次,一次是显式销毁,一次是隐式销毁。通常,只有在执行异常操作(可能涉及使用placement new)时,才显式调用析构函数。

如果确实需要执行类似操作,只需创建一个附加函数,并从外部和构造函数本身调用它,但让我们看看当确实需要此类调用时会发生什么:

#include<new>

class A
{
//members
};

int main()
{
//allocate buffer
char* buffer = new char[sizeof(A)];
//construct A on that memory space
A * ptrToA = ::new (buffer) A();
//destroy the object
ptrToA->~A();
//deallocate the buffer
delete[] buffer;
}
#包括
甲级
{
//成员
};
int main()
{
//分配缓冲区
char*buffer=新字符[sizeof(A)];
//在该内存空间上构造一个
A*ptrToA=::新(缓冲区)A();
//摧毁目标
ptrToA->~A();
//释放缓冲区
删除[]缓冲区;
}
您可以找到新用法的一个实例是标准 容器。分配器负责分配 缓冲区(分配成员)和对象是在该缓冲区上构造的 缓冲区,因为它们被添加到容器中。例如,当你 保留在矢量对象上,它为N个对象保留空间 为N个对象分配空间,但不构造它们。那么什么时候 你可以把你推回去,等等,来添加元素,它们是在上面创建的 缓冲器基本上,这是一种减少系统开销的技术 重复调用内存分配函数。然后,当完成时 向量析构函数将销毁调用析构函数的对象 显式地为其中的所有对象分配,然后调用deallocate()函数
分配器释放内存的功能。希望这能有所帮助。

如果您真的需要这样做,只需创建一个附加函数并从外部和构造函数本身调用它,但让我们看看当您确实需要这样的调用时会发生什么:

#include<new>

class A
{
//members
};

int main()
{
//allocate buffer
char* buffer = new char[sizeof(A)];
//construct A on that memory space
A * ptrToA = ::new (buffer) A();
//destroy the object
ptrToA->~A();
//deallocate the buffer
delete[] buffer;
}
#包括
甲级
{
//成员
};
int main()
{
//分配缓冲区
char*buffer=新字符[sizeof(A)];
//在该内存空间上构造一个
A*ptrToA=::新(缓冲区)A();
//摧毁目标
ptrToA->~A();
//释放缓冲区
删除[]缓冲区;
}
您可以找到新用法的一个实例是标准 容器。分配器负责分配 缓冲区(分配成员)和对象是在该缓冲区上构造的 缓冲区,因为它们被添加到容器中。例如,当你 保留在矢量对象上,它为N个对象保留空间 为N个对象分配空间,但不构造它们。那么什么时候 你可以把你推回去,等等,来添加元素,它们是在上面创建的 缓冲器基本上,这是一种减少系统开销的技术 重复调用内存分配函数。然后,当完成时 向量析构函数将销毁调用析构函数的对象 显式地为其中的所有对象分配,然后调用deallocate()函数 分配器释放内存的功能。希望这有帮助。

构造函数中有“c()”用于new,即

c objC = new c();
如果您想在类实例的实际构造之外调用构造函数,那么您要么不了解构造函数的用途,要么试图将不应该存在的功能放在构造函数中。

构造函数在那里“c()”与new一起使用,即

c objC = new c();

如果您想在类实例的实际构造之外调用构造函数,那么您要么不了解构造函数的用途,要么试图将不应该存在的功能放在构造函数中。

您可以使用
typeof
调用实例类的构造函数:

class c
{
public:
   void add() ;
   c();
   ~c() ;
};

void main()
{
 c objC  ;
 objC.add() ;
 objC.~c() ; // this line compiles (but is a bad idea)
 typeof objC otherObjC;  // so does this.
}
这不会影响实例
objC
的值,而是使用
objC
的类构造函数创建一个新实例
otherObjC


注意:如果静态类型是您拥有的实例的动态类型的基类,这可能会做一些您不期望的事情。

您可以使用
typeof
调用实例类的构造函数:

class c
{
public:
   void add() ;
   c();
   ~c() ;
};

void main()
{
 c objC  ;
 objC.add() ;
 objC.~c() ; // this line compiles (but is a bad idea)
 typeof objC otherObjC;  // so does this.
}
这不会影响实例
objC
的值,而是使用
objC
的类构造函数创建一个新实例
otherObjC

注意:如果静态类型是您拥有的实例的动态类型的基类,那么这可能会做一些您不期望的事情。

尝试一下:

obj.ClassName::ClassName();//它在VC 6.0编译器中工作

请尝试以下操作:


obj.ClassName::ClassName();//它在VC 6.0编译器中工作

我认为,如果您确保使用调用placement new替换/重新创建实例,则可以显式调用析构函数:

class c
{
public:
   void add() ;
   c();
   ~c() ;
};

int main()
{
 c objC  ;
 objC.add() ;
 objC.~c() ; // this line compiles
 new (&objC) c;  // placement new invokes constructor for the given memory region
}
我从未在实践中见过这种情况,但从逻辑上讲它应该可以工作(除非c的构造函数可以抛出,在这种情况下,我想,在堆栈展开过程中,地狱可能会崩溃)

然而,您可能想要的只是分配:

objC = c();
如果析构函数有您感兴趣的副作用,请实现assign