繁体   English   中英

const/non-const 重载解决问题

[英]Trouble with const/non-const overload resolution

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

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

在 class 之外,我调用 Get() function。

float foo = classAInstance.Get(i);

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

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

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

当一个可访问的成员可用时,为什么编译器会尝试使用不可访问的成员? 是否有一种公认的方式来强制编译器选择正确的重载? 是否在某处引用了成员函数的解析规则?

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

重载解析是一种机制,用于选择最佳 function 来调用给定的表达式列表,这些表达式将成为调用的 arguments 和一组可以根据调用上下文调用的候选函数。 The selection criteria for the best function are the number of arguments, how well the arguments match the parameter-type-list of the candidate function, how well (for non-static member functions) the object matches the implicit object parameter, and certain other候选 function 的属性。 [注:重载决议选择的function不保证适合上下文。 其他限制,例如 function 的可访问性,可以使其在调用上下文中的使用格式不正确。 ——尾注]

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


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

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被隐式构造和绑定。

重载解决首先完成,然后访问检查。

如果你同时有一个 const 和一个非常量重载,这可以通过 object 的 constness 解决,需要 function。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM