1

我已经问了一个与私有析构函数相关的问题(使用使析构函数成为私有),但我以下面的问题结束,但我仍然不明白确切的答案。

问题:

当我创建具有私有析构函数的类对象时,为什么会调用私有析构函数?但不是当我创建一个普通对象时。

案例一

// 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

编辑

我已经知道,当我们“仅需要基于堆的对象”时,需要将析构函数设为保护/私有。

http://en.wikibooks.org/w/index.php?title=More_C%2B%2B_Idioms%2FRequiring_or_Prohibiting_Heap-based_Objects&diff=2567824&oldid=2202430&utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+MoreCppIdiomsWikibook+%28Wikibooks+-+Changes+related+to+ %22More+C%2B%2B+成语%22+[en]%2 9

4

5 回答 5

2

静态函数是类的函数,所以它可以访问private这个类的函数,这就是为什么 1 case 可以正常工作的原因。

在第一种情况下 - 对象将在 function 中创建Instance,它可以访问此类的构造函数。由于声明了对象static- 它只会在程序结束时被销毁,因为对象是在类函数中创建的 - 可以访问析构函数。

在第二种情况下 - 您正在尝试MyClassmain函数中创建类型的对象,它不是类函数,因此它无法访问 c-tor/d-tor。

于 2013-10-21T11:00:42.017 回答
1

具有静态存储持续时间的对象在返回main或调用 后被销毁std::exit。标准的第 3.6.3 节描述了这种破坏。从 C++11、3.6.3、

作为从 main 返回的结果和调用 std::exit 的结果,调用具有静态存储持续时间的已初始化对象(即其生命周期已开始的对象)的析构函数。

请注意,没有提及析构函数的可访问性(公共/受保护/私有)。适当的析构函数称为句号。

12.4 节介绍了可访问性。C++11 12.4 第 11 段(C++03 中的第 10 段)指出

如果声明了类类型或其数组的对象,并且在声明时无法访问该类的析构函数,则程序是格式错误的。

析构函数可以在静态函数中访问MyClass::GetInstance(),因此在该函数中声明的块范围静态变量是可以的。析构函数在 中不可访问main(),所以在中声明的自动变量main是不行的。

于 2013-10-21T12:01:50.937 回答
1

在这两种情况下,都需要析构函数在对象的静态或自动生命周期结束时销毁对象,因此必须在声明对象的地方可访问。

在第一种情况下,对象是在类的成员中声明的,因此析构函数是可访问的并且编译成功。

在第二种情况下,对象是在非成员函数中声明的,因此析构函数不可访问,编译失败。

于 2013-10-21T11:01:52.773 回答
0

所有对象在超出范围时都会被破坏,而声明为静态的对象在程序结束时也会超出范围,这正是您在第一个示例中看到的。将析构函数声明为私有仅意味着您可以在同一个类中创建(和销毁)实例。

于 2013-10-21T11:01:35.793 回答
0

尽管我不明白您要达到什么目的,但错误很明显:

在您的第一种情况下,构造对象的行位于类内部,因此可以访问所有私有方法。

在您的第二种情况下,构造在类之外,因此无法访问私有成员。

于 2013-10-21T11:02:16.720 回答