V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
James369
V2EX  ›  C++

由于找不到 C++版块,只能在这里问个类成员隐藏的问题。

  •  
  •   James369 · 2020-12-16 15:08:18 +08:00 · 2151 次点击
    这是一个创建于 1198 天前的主题,其中的信息可能已经有所发展或是发生改变。
    很喜欢 Objective-C 语言,特别是它的分类 Category 和扩展 Extension 的能力。现在有个项目是 C++的,碰到一个小需求,就是类实现中的某些方法,想弄成私有,并且不要在.h 头文件中声明(不声明还编译报错:prototype for '类名::函数名'does not match any in class'类名')

    简单的说,就是想彻底隐藏类中的某些方法(使其在头文件不可见)。这要是在 ObjectiveC 中用 Extension 分分钟就搞定了,而且代码也不冗余,C++不知道如何做?
    17 条回复    2020-12-16 17:03:28 +08:00
    codehz
        1
    codehz  
       2020-12-16 15:12:44 +08:00   ❤️ 1
    (你可以把私有函数不做成方法*
    直接在 cpp 文件里做成普通 static 函数
    ,不要试图用两个不同的头文件,有 abi 问题
    paoqi2048
        2
    paoqi2048  
       2020-12-16 15:15:14 +08:00
    /go/cpp C++版块在这里
    James369
        3
    James369  
    OP
       2020-12-16 15:18:43 +08:00
    @codehz 也是个办法,算是曲线救国,要多传一个 对象指针进去。
    Aspector
        4
    Aspector  
       2020-12-16 15:20:06 +08:00
    用 pointer to implementation ?再写一个 impl 类不放头文件,用一个私有成员指针指过去。
    zacharyjia
        5
    zacharyjia  
       2020-12-16 15:24:23 +08:00
    抽一个父类出来做接口?对外只暴露父类,可能需要配合工厂模式食用?不过感觉比 1 楼的方法更复杂了
    imkerberos
        6
    imkerberos  
       2020-12-16 15:27:12 +08:00
    impl 模式.
    wutiantong
        7
    wutiantong  
       2020-12-16 15:47:17 +08:00
    十年前 obj-c 还没有 extension 时,我就用 impl 模式写过这种需求
    enenaaa
        8
    enenaaa  
       2020-12-16 15:49:16 +08:00
    看看 qt 源码, 很多这样的写法。
    geelaw
        9
    geelaw  
       2020-12-16 15:52:27 +08:00 via iPhone
    不存在这种功能,C++ 里私有成员是接口而不是实现细节,这主要体现在字段影响内存布局、友元、可以被重写的私有虚拟成员、名字解析(私有成员会参与名字解析)。

    曲线救国的思路是 pimpl 或者接口化。
    aneostart173
        10
    aneostart173  
       2020-12-16 16:13:55 +08:00
    外面只暴露接口,里面在 impl 一个类,或者只提供 c api 。
    lakehylia
        11
    lakehylia  
       2020-12-16 16:19:53 +08:00
    纯虚函数接口配合 createInstance 和 releaseInstance,妥妥的
    weidaizi
        12
    weidaizi  
       2020-12-16 16:23:06 +08:00
    //////////////////////////////
    // foo.h
    class Foo
    {
    public:
    static Foo* newFoo();

    void Bar();
    }

    -----------------------------------------------------------

    //////////////////////////////
    // foo_impl.h
    #include "foo.h"

    class FooImpl : public Foo
    {
    public:
    void Bar();

    private:
    void Xyz();
    };

    -----------------------------------------------------------

    然后对外只暴露 foo.h 即可
    Wirbelwind
        13
    Wirbelwind  
       2020-12-16 16:48:18 +08:00
    .h 和.cc 分离 想要暴露函数的写在.h 里面
    不暴露的接口直接在.cc 里面写 第一个参数是这个类,其他不变
    class A{}
    Wirbelwind
        14
    Wirbelwind  
       2020-12-16 16:50:43 +08:00   ❤️ 1
    weidaizi
        15
    weidaizi  
       2020-12-16 16:52:59 +08:00
    上面那个回复,忘记写 virtual 了,囧

    //////////////////////////////
    // foo.h
    class Foo
    {
    public:
    static Foo* newFoo();

    virtual void Bar();
    }

    -----------------------------------------------------------

    //////////////////////////////
    // foo_impl.h
    #include "foo.h"

    class FooImpl : public Foo
    {
    public:
    virtual void Bar() override;

    private:
    void Xyz();

    private:
    .......
    };

    -----------------------------------------------------------

    然后对外只暴露 foo.h 即可
    jimmyismagic
        16
    jimmyismagic  
       2020-12-16 16:56:37 +08:00
    上面说得很清楚,暴露个父类出来,可以是纯虚类,也可以是模板类
    Wirbelwind
        17
    Wirbelwind  
       2020-12-16 17:03:28 +08:00
    还有个使用 using 的办法
    不建议继承写法
    项目里面这样的写法多了之后 后期维护的人会头大 不简洁直观
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1280 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 17:48 · PVG 01:48 · LAX 10:48 · JFK 13:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.