草庐IT

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

coder 2024-02-05 原文

如果有人问过这个问题,请原谅我,我没有找到我的具体问题的任何答案。

我正在创建的库中有一个类,我希望某些类能够创建和销毁,而其他类能够访问其他公共(public)函数。拥有一个 friend class 也不是我想要的,因为 friend 类将可以访问我不想要的成员变量和成员函数。我偶然发现 this idiom这几乎可以工作,除了析构函数,因为它不能接受额外的参数。有了这个成语,我得到:

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
};

正如上面代码中提到的,该解决方案不允许只有 class B 可以访问析构函数。

虽然上述问题在任何方面都不会破坏交易,因为我总是可以公开 ctor 和 dtor 并只说“RTFM”。

我的问题是:

是否有某种方法可以限制对特定类(但仅限于 ctor 和 dtor)的 ctor 和 dtor 的访问,同时遵守更广为人知的语法(如果人们需要,可以将东西放在堆栈上,通过 delete 销毁等。 )?

非常感谢任何帮助!

解决方案

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
};

B.h

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

    private:
        A* m_a;
}

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; }

或者,如果 B.hA.h 中需要 DeletableA 类(由于内联、模板化或希望拥有所有 class A A.h 中的相关类),它可以通过构造函数上的“密码”移动到那里,这样其他类就不能创建一个。即使将公开析构函数,其他类也永远不会获得要删除的 DeletableA

显然,此解决方案要求 class B 知道创建 Deletable A 的实例(或者如果类未在 A.h 中公开,则创建一般类) 并且只存储通过公共(public)函数公开的 A*,但是,这是建议的最灵活的设置。

虽然某些其他类仍然可以创建 class A 的子类(因为 class A 不是“final”),您可以添加另一个“密码” "给 A 的构造函数,以防止您愿意的话。

最佳答案

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

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

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

  • 对于动态对象,您可以从具有 protected 虚拟析构函数或命名的自毁函数的接口(interface)派生类 A,它具有类 B 作为 friend 。 B 然后可以通过转换为它有权访问的接口(interface)来销毁任何动态 A 对象。

显式调用析构函数的代码应得到它所得到的一切。

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

关于c++ - 限制对 C++ 构造函数和析构函数的访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25922313/

有关c++ - 限制对 C++ 构造函数和析构函数的访问的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  5. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  6. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  7. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  8. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  9. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  10. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

随机推荐