我问了一个与私有析构函数相关的问题(Use of making destructor private),但我已经以下面的问题结束了,但我仍然不明白答案。
问题:
为什么在创建具有私有析构函数的类的对象时会调用私有析构函数?但是,当我创建一个普通对象时,不是这样。
// myclass.h
#include <iostream>
class MyClass {
public:
static MyClass& GetInstance();
void Display();
private:
MyClass();
virtual ~MyClass();
};
MyClass::MyClass() {
std::cout << "Constructor " << std::endl;
}
MyClass::~MyClass() {
std::cout << "Destructor" << std::endl;
}
MyClass& MyClass::GetInstance() {
static MyClass _instance;
return _instance;
}
void MyClass::Display() {
std::cout << "Hello" << std::endl;
}
// main.cpp
#include "myclass.h"
#include <iostream>
int main() {
MyClass::GetInstance().Display(); //case1
std::cout << "main finished!" << std::endl;
return 0;
}
// output
Constructor
main finished
Destructor.
// myclass.h
#include <iostream>
class MyClass {
public:
void Display();
MyClass();
virtual ~MyClass();
};
MyClass::MyClass() {
std::cout << "Constructor " << std::endl;
}
MyClass::~MyClass() {
std::cout << "Destructor" << std::endl;
}
MyClass& MyClass::GetInstance() {
static MyClass _instance;
return _instance;
}
void MyClass::Display() {
std::cout << "Hello" << std::endl;
}
// main.cpp
#include "myclass.h"
#include <iostream>
int main() {
MyClass testObj;
std::cout << "main finished!" << std::endl;
return 0;
}
// Error
1>e:\programs\cpp_test\src\main.cpp(38): error C2248: 'MyClass::MyClass' : cannot access private member declared in class 'MyClass'
1> e:\programs\cpp_test\static_single_test.h(11) : see declaration of 'MyClass::MyClass'
1> e:\programs\cpp_test\static_single_test.h(6) : see declaration of 'MyClass'
1>e:\programs\cpp_test\src\main.cpp(38): error C2248: 'MyClass::~MyClass' : cannot access private member declared in class 'MyClass'
1> e:\programs\cpp_test\static_single_test.h(12) : see declaration of 'MyClass::~MyClass
修改
我已经知道当我们“只需要基于堆的对象时”需要使析构函数受保护/私有。
答案 0 :(得分:2)
静态函数是类的函数,因此它可以访问此类的private
函数,这就是为什么1个案例可以正常工作的原因。
在第一种情况下 - 将在函数Instance
中创建对象,该对象可以访问此类的构造函数。由于object被声明为static
- 它只会在程序结束时被销毁,因为对象是在类函数中创建的 - 可以访问析构函数。
在第二种情况下 - 您试图在MyClass
函数中创建类型main
的对象,这不是类函数,因此它无法访问c-tor / d-tor。 / p>
答案 1 :(得分:1)
从main
返回或致电std::exit
后,具有静态存储持续时间的对象将被销毁。标准的第3.6.3节描述了这种破坏。来自C ++ 11,3.6.3,
具有静态存储持续时间的初始化对象(即,其生命周期已开始的对象)的析构函数被调用为从main返回并且由于调用std :: exit而被调用。
请注意,没有提到析构函数的可访问性(public / protected / private)。适当的析构函数叫做句点。
第12.4节涵盖了可访问性。 C ++ 11 12.4第11段(C ++ 03第10段)指出
如果声明了类类型的对象或其数组,并且在声明时无法访问该类的析构函数,则程序格式不正确。
析构函数可以在静态函数MyClass::GetInstance()
中访问,因此在该函数中声明的块作用域静态变量是可以的。 main()
中无法访问析构函数,因此main
中声明的自动变量不正常。
答案 2 :(得分:0)
当超出范围时,所有对象都被破坏,并且当程序结束时,声明为static的对象超出范围,这正是您在第一个示例中看到的。析构函数声明为private只意味着您可以在同一个类中创建(和销毁)实例。
答案 3 :(得分:0)
在这两种情况下,析构函数都需要在静态或自动生命周期结束时销毁对象,因此必须可以在声明对象的地方访问它。
在第一种情况下,对象在类的成员内声明,因此可以访问析构函数并编译成功。
在第二种情况下,对象在非成员函数中声明,因此析构函数不可访问,编译失败。
答案 4 :(得分:0)
虽然我不明白你想要实现什么,但错误是显而易见的:
在第一种情况下,构造对象的行在类中,因此可以访问所有私有方法。
在你的第二个案例中,构造不在课堂之内,因此无法访问私人成员。