限制对C++构造函数和析构函数的访问

Enc*_*ble 6 c++ constructor destructor

请原谅我,如果已经提出这个问题,我没有找到任何特定问题的答案.

我在库中创建了一个类,我希望某些类能够创建和销毁,其他类可以访问其他公共函数.有一个friend class不是我想要的,因为朋友类将访问我不想要的成员变量和成员函数.我偶然发现了这个几乎可以工作的习语,除了析构函数,因为它不能采用其他参数.有了这个成语,我得到:

class B;
class A
{
    public:
        class LifecycleKey
        {
            private:
                LifecycleKey() {}
                friend class B;
        };

        A(LifecycleKey); // Now only class B can call this
        // Other public functions

    private:
        ~A(); // But how can I get class B to have access to this?

        void somePrivateFunction();

        // Members and other private functions
};
Run Code Online (Sandbox Code Playgroud)

如上面的代码中所提到的,该解决方案不允许仅class B访问析构函数.

虽然上述问题都没有任何影响,因为我总是可以将ctor和dtor公之于众,并且只是说"RTFM".

我的问题是:

有没有办法限制访问ctor和dtor到特定的类(但只有ctor和dtor),同时坚持更熟知的语法(如果人们想要的东西在堆栈上,通过删除销毁,等等)?

任何帮助是极大的赞赏!

A.h

class B;
class A
{
    protected:
        A() {}
        virtual ~A() {}
        A(const A&); // Implement if needed
        A(A&&); // Implement if needed

    public:
        // Public functions

    private:
        void somePrivateFunction();

        // Members and other private functions
};
Run Code Online (Sandbox Code Playgroud)

B.h

class B
{
    public:
        B();
        ~B();
        const A* getA() const;

    private:
        A* m_a;
}
Run Code Online (Sandbox Code Playgroud)

B.cpp

namespace {
    class DeletableA : public A {
        public:
            DeletableA() : A() {}
            DeletableA(const DeletableA&); // Implement if needed
            DeletableA(DeletableA&&); // Implement if needed
            ~DeletableA() {}
    }
}

#include B.h
B::B() : m_a(new DeletableA()) {}
B::~B() { delete static_cast<DeletableA*>(m_a); }
const A* B::getA() const { return m_a; }
Run Code Online (Sandbox Code Playgroud)

或者,如果DeletableA需要类B.hA.h(由于内联,模板或希望将所有class A相关的类放入其中A.h),可以使用构造函数上的"传递键"将其移动到那里,以便其他类不能创建一个.即使析构函数将被暴露,也没有其他类可以DeletableA删除.

显然,这个解决方案需要class B知道如何制作实例Deletable A(或者如果它没有暴露在一般地创建类A.h),并且只存储A*通过公共函数公开的存储,但是,它是建议的最灵活的设置.

虽然某些其他类仍然可以创建class A(因为class A不是"final")的子类,但是如果您愿意,可以向A的构造函数添加另一个"密钥"以防止此类行为.

Che*_*Alf 1

为了实现这一目标,该类B应该是唯一能够实例化和销毁该类对象的类A

  • 对于静态和自动变量,只需要限制对构造函数的访问,并且您已经这样做了。

  • 对于动态分配的对象,您可以限制对其释放函数 、operator delete和 的访问operator delete[],并将析构函数保留为公共。这会禁止除删除对象之外的其他代码B

  • 对于动态对象,您可以从具有虚拟析构函数或命名自毁函数的A接口派生类,该函数将类作为友元。然后可以通过强制转换到它有权访问的接口来销毁任何动态对象。protectedBBA

显式调用析构函数的代码值得得到任何好处。

请记住,您永远不会构建针对恶意代码的坚不可摧的防御,您只是构建合理的检测和编译时报告无意的错误使用。