const 和非 const getter:C2248:无法访问类中声明的私有成员

Posted

技术标签:

【中文标题】const 和非 const getter:C2248:无法访问类中声明的私有成员【英文标题】:const and non const getter : C2248: cannot access private member declared in class 【发布时间】:2015-10-20 09:43:11 【问题描述】:

我有一个实现std::vector 的getter 的类。派生类可以更改向量的内容,而任何其他类可以读取它(或在我的情况下复制),但不能更改它。

SSCCE 与 Visual Studio 2010(但也应与任何其他版本一起编译)。

所以在基类中我这样实现了getter:

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <cstring>
#include <string>
#include <vector>

    class X
    
    public:
        inline std::vector<std::string> const &getChilds(void) const
        
            return mChilds;
        

        void mutateInternal(void)
        
            mState != mState;
        

    protected:
        inline std::vector<std::string> &getChilds(void)
        
            return mChilds;
        

    private:
        std::vector<std::string> mChilds;
        bool mState;
    ;

// Now in the derived class

    class Y : public X
    
    public:
        Y(void)
        
            std::vector<std::string> &childs = getChilds();
            childs.push_back("Test");
        

    ;

// In the non derived class:

    class Z
    
    public:
        void myfunction(void)
        
            Y y;

            std::vector<std::string> s = y.getChilds();
            if(s.size() == 0)
                y.mutateInternal();

        

    ;


int main(int argc, char *argv[])

    return 0;

但我得到了错误

1>junk.cpp(49): error C2248: "X::getChilds": cannot access private member declared in class.
1>          junk.cpp(18): Siehe Deklaration von 'X::getChilds'
1>          junk.cpp(10): Siehe Deklaration von 'X'

我真的不明白这有什么问题,以及为什么编译器不采用 const 的公共版本,而是坚持使用非 const。

即使我将变量更改为 const &amp;s(在这种情况下也无济于事),我仍然会遇到同样的错误。

更新:

编辑了用于调用 const 和非 const 函数的 SSCCE。

【问题讨论】:

改用std::vector&lt;std::string&gt; s = static_cast&lt;const Y&amp;&gt;(y).getChilds(); 我从不推荐使用语法重载,更不用说仅在 constness 中重载。我知道这并不能回答您的问题 - 这就是我将其写为评论的原因。 一个简单的解决方案是为函数赋予不同的名称,但由于无论如何您都提供对子类的不受限制的访问,getter 本身是有问题的,最简单的解决方案是使成员变量受保护。 @molbdnilo,根据我的经验,我发现吸气剂更有用。它们通常会得到优化,但是当我需要更改某些内容(例如日志访问等)时,我不必修改我的代码。 @molbdnilo,直接访问也不允许我在以后更改实现,因为那时我有一个直接耦合。 【参考方案1】:

在这种情况下应该是

const Y y;

Z::my_function 中调用const 版本的函数。 Live 或者直接投到const Y,比如

std::vector<std::string> s = const_cast<const Y&>(y).getChilds();

您的情况不起作用,因为只有在重载解决后才会应用访问检查,在调用y.getChilds() 时将选择非常量重载,因为它具有最佳匹配。

【讨论】:

但这不是说我不能调用任何非常量函数吗?毕竟,在某些情况下,类可能需要更新其内部状态(SSCCE 中没有显示)。 我更新了我的示例。无论如何,我认为编译器可以自己推断出来。如果我必须添加这个丑陋的演员表,那么我也可以使用人为不同的函数名,这样可以使代码更清晰易读。 @Devolus 不能,因为非常量版本是最佳匹配,但它处于受保护状态。 我想我现在明白了这个问题(即使我不喜欢它:))。行。谢谢!

以上是关于const 和非 const getter:C2248:无法访问类中声明的私有成员的主要内容,如果未能解决你的问题,请参考以下文章

返回一个const和非const包装器对象

typedef 模板,接受指向 const 和非 const 函数的指针

const函数

获取 const 方法的地址

返回数组列表的 const 引用

C 中的泛型编程 - void*- const 正确性