const /非const重载决议的问题

时间:2011-06-04 21:52:24

标签: c++ visual-studio-2010 overloading overload-resolution

我有一个看起来像这样的课程:

class ClassA
{
  public:
    float Get(int num) const;
  protected:
    float& Get(int num);
}

在课堂之外,我调用了Get()函数。

float foo = classAInstance.Get(i);

我希望这可以调用公共版本,但是Visual Studio会出错:

error C2248: 'ClassA::Get' : cannot access protected member declared in class 'ClassA'

当注释掉受保护的重载并删除对它的所有引用时,代码将编译。

为什么编译器会在可访问的成员可用时尝试使用不可访问的成员?是否有一种可以接受的方法来强制编译器选择正确的重载?是否有参考成员函数的解决规则?

2 个答案:

答案 0 :(得分:7)

确实,在进行可访问性检查之前会发生重载决策。标准的第13.3节([over.match])说:

  

重载解析是一种机制,用于在给定表达式列表的情况下选择要调用的最佳函数   作为调用的参数和一组可以根据上下文调用的候选函数   电话。最佳函数的选择标准是参数的数量,参数的好坏程度   匹配候选函数的参数类型列表,如何(对于非静态成员函数)   object匹配隐式对象参数以及候选函数的某些其他属性。 [ 注意:   重载决策选择的功能不能保证适合上下文。其他   限制(例如函数的可访问性)可以使其在调用上下文中的使用不正确。    - 结束说明]

通常的解决方法是为公共和受保护的函数提供不同的名称。


注意,这有时很有用,例如:

class Blah
{
    const std::string& name_ref;

    Blah(const char*) = delete;

public:
    Blah(const std::string& name) : name_ref(name) {}

    void do_something_with_name_ref() const;
};

std::string s = "Blam";
Blah b(s); // ok

请注意,name_ref只会被读取,因此适合const。但是,const引用可以绑定到临时对象,将name_ref绑定到临时引用将是一个悬空引用,导致do_something_with_name_ref()中的未定义行为。

Blah c("Kablooey!"); // would be undefined behavior
                     // the constructor overload makes this a compile error

私有构造函数重载可以防止临时构造和绑定临时std::string

答案 1 :(得分:5)

首先完成过载分辨率,稍后进行访问检查。

如果同时具有const和非const重载,则通过调用该函数的对象的常量来解决此问题。