【问题标题】:private non-const and public const member function - coexisting in peace?私有非常量和公共 const 成员函数 - 和平共存?
【发布时间】:2010-11-15 03:16:52
【问题描述】:

我正在尝试创建一个具有两个同名方法的类,用于访问私有成员。一种方法是公共的和 const 限定的,另一种是私有的和非常量的(由朋友类使用,通过引用返回的方式修改成员)。

不幸的是,我收到编译错误(使用 g++ 4.3):当使用非常量对象调用该方法时,g++ 抱怨我的方法的非常量版本是私有的,即使是公共(常量)版本存在。

这看起来很奇怪,因为如果私有非常量版本不存在,一切都可以正常编译。

有什么办法可以使这个工作吗? 它可以在其他编译器上编译吗?

谢谢。

例子:

class A
{
public:
    A( int a = 0 ) : a_(a) {}
public:
    int   a() const { return a_; }
private:
    int & a()       { return a_; } /* Comment this out, everything works fine */
    friend class B;
private:
    int a_;
};


int main()
{
    A       a1;
    A const a2;

    cout << a1.a() << endl; /* not fine: tries to use the non-const (private) version of a() and fails  */
    cout << a2.a() << endl; /* fine: uses the const version of a() */
}

【问题讨论】:

  • 为什么会失败? C++ 允许从非 const 转换为 const,相对于函数参数。

标签: c++ compiler-errors


【解决方案1】:

重载解析发生在访问检查之前,因此当您在非常量 A 上调用 a 方法时,会选择非常量成员作为更好的匹配。然后编译器由于访问检查而失败。

没有办法“使这项工作”,我的建议是重命名私有函数。是否需要私有访问器?

【讨论】:

  • 隐藏类是我最好的选择 - 就像在更大的类中使用 Node 结构。
  • 那太糟糕了。我怀疑会是这样,但我不明白为什么会这样。希望有人能告诉我为什么需要这样,这样我就可以轻松休息了。我想要这种行为的原因是因为我通常将我的 getter 和 setter 编写为同一方法的两个 const/non-const 版本,没有“get”/“set”前缀。对于这个特定的类,我不想让除一个之外的任何类使用设置器(因此是朋友类声明)。
  • 当函数执行相同或相似的逻辑运算但使用不同类型的参数时,重载函数的能力主要有用(特别适用于在模板中编写通用代码)。检索某物的值与获取某物的引用以更新它是不同的操作。出于这个原因,给函数起不同的名字是有意义的(至少对我来说!)。如果您尝试保持相同的名字,我认为您是在“逆流而上”。
  • 有趣的方式来看待它。但是,我总是以不同的方式看待它,例如:stl 容器有一个 begin()/end() 成员,它们根据对象的 cv 资格自动返回迭代器或 const_iterator(是的,c++0x 正在添加 cbegin()/ cend() 显式请求 const 版本,即使 object 是 non_const,在使用 auto 关键字时特别有用)。我会认为这种情况完全相同,在这个例子中我碰巧返回了一个引用,但它可能是一个 const/non const 指针。如果函数不是私有的,一切都会好起来的...... :(
【解决方案2】:

如果声明的对象是const,它只会选择const 版本,否则它将选择非const 版本(即使这会导致错误)。

这应该可行:

cout << ((const A*)&a1)->a() << endl;

或者这个:

A const& ra1 = a1;
cout << ra1.a() << endl;

【讨论】:

  • 我想我更喜欢const_cast&lt;const A&amp;&gt;(a1).a()。看起来会更安全一些。
  • 是的,如果您要使用演员表,这是最好的方法。我不认为它比第二种方法更安全,但是,编译器将为引用的赋值强制执行完全类型安全。无论如何,我认为您可以通过例如在传递这些东西时将方法签名从 A&amp; 更改为 A const&amp; 来实现这一点,而不是像这个明显人为的示例中那样直接操作它们。
  • 我不明白为什么 Charles Bailey 的答案比 Tim Sylvester 的这个答案(恕我直言,正确且有效)的投票率更高,这表明 没有办法“使这项工作”。实际上,我来到这里是因为我知道我在代码中的某个地方解决了这样的问题,但我忘记了在哪里以及如何。 (顺便说一句。我完全按照上面描述的方法解决了。可能是,下次我应该尝试在我自己的本地源代码上谷歌......)
猜你喜欢
  • 2012-10-25
  • 2010-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多