繁体   English   中英

当const方法是公共的并且非const方法受保护时,为什么C ++不会转换为const?

[英]Why doesn't C++ cast to const when a const method is public and the non-const one is protected?

我用两个get方法创建了一个类,一个是const,一个是非const。 const方法是公共的,因此用户可以查询向量。 非const方法受到保护,因此我可以使用它来修改我需要的数据。

但是,当我尝试使用该类并调用get方法时,编译器会抱怨非const方法受到保护。 相反,我必须使用const_cast将对象强制转换为const,因此我可以使用public方法。

有办法解决这个问题吗? 为什么编译器不会执行转换,因为有一个公共方法? 如果我删除受保护的版本并且只保留const版本,它可以正常工作,因此它会在这种情况下进行转换。 转换为const始终是安全的。 它正在消除常量问题。

成员访问控制是调用成员函数时发生的最后一件事。 它发生在名称查找,模板参数推导,重载解析等之后。 它最后完成的原因是因为决定更改成员的访问控制不应该突然改变客户端代码的执行。

想象一下在重载解析之前检查了访问权限,并且您在该库中使用了库和某个成员函数。 然后,图书馆作者将该功能设为私有。 突然,您的代码开始使用不同的重载,并以完全不同的方式运行。 库作者可能打算任何使用该函数重载的人都应该停止使用它,但他们并不打算改变每个人的代码。 但是,由于标准实际上已定义,因此您的代码现在开始使用私有成员时出错,而不是表现不同。

解决方案是简单地更改受保护成员函数的名称,以便不考虑它。

编译器决定要调用哪个成员函数会考虑可访问性。 也就是说,即使无法访问受保护和私有函数,它们仍然可见

为什么? 一个原因是,如果您通过重载解析忽略了不可访问的函数,则可以通过更改其可访问性来更改调用的函数。 使用当前规则,您只能导致编译代码无法编译,或导致当前无法编译的代码或更改某些内容而不影响代码的含义。 您无法更改访问说明符并以静默方式调用其他函数。

作为一个人为的例子,这是一个非常可怕的类接口:

public:
    // Returns the amount of change tendered for this transaction.
    MoneyAmount change() const;

private:
    // Account for a change of currency. Charges standard moneychanger's fee.
    MoneyAmount change(Currency toCurrency = Currency::USD);

如果从重载解析中删除了不可访问的函数,客户端代码可以调用change()就好了。 如果稍后第二个change(Currency)功能被公开并且第一个被删除,那么该代码会突然默默地调用具有完全不同目的的另一个功能。 当前规则阻止访问说明符的更改改变编译程序的行为。

在C ++中,方法选择(重载分辨率)在考虑公共/私有访问控制之前发生。

使用受保护的setter方法(或数据成员)而不是非const getter方法。

如果你有s.th.没有区别。 喜欢

class A {
    SomeType foo_;
protected:
    SomeType& foo() { return foo_; }

public:
    const SomeType& foo() const { return foo_; }
};

要么

class A {
protected:
    SomeType foo_;

public:
    const SomeType& foo() const { return foo_; }
};

这就是C ++的自然行为,如果调用者代码类的对象是非const,那么非转换,被定义为受保护的。 您需要将类的对象定义为const或在类的对象上使用const-cast,这将导致调用方法的const版本。

#include <iostream>
class Foo {
    public:
        const void bar() const { std::cout << " const version called\n";}  
    protected:
        void bar() { std::cout << " non const version called\n";}  
};

int main(int argc, char** argv)
{
    const Foo c;
    c.bar(); // -> work

    Foo c1;
    c1.bar(); // compiler complain -> void Foo::bar() is protected
    const_cast<const Foo&>(c1).bar(); // fine 
}

暂无
暂无

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

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