C++ 为什么';tc++;当常量方法是公共的且非常量方法受到保护时,是否强制转换为常量?

C++ 为什么';tc++;当常量方法是公共的且非常量方法受到保护时,是否强制转换为常量?,c++,constants,C++,Constants,我创建了一个包含两个get方法的类,一个是const,一个是non-const。const方法是公共的,因此用户可以查询向量。non-const方法是受保护的,因此我可以使用它来修改我需要的数据 但是,当我尝试使用该类并调用get方法时,编译器会抱怨非常量方法受到保护。相反,我必须使用const_cast将对象强制转换为const,这样我可以得到public方法 有办法解决这个问题吗?既然有一个公共方法,为什么编译器不自己执行强制转换呢?如果我删除了受保护的版本,只保留const-one,它就可

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

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


有办法解决这个问题吗?既然有一个公共方法,为什么编译器不自己执行强制转换呢?如果我删除了受保护的版本,只保留const-one,它就可以正常工作,所以在这种情况下它会执行强制转换。向const施法总是安全的。在C++中,方法选择(重载解析)发生在考虑公有/私有访问控制之前。< /P> < P>使用保护的SETTER方法代替(或数据成员)代替非conter吸收器方法。< /P> 如果你有s.th也没什么区别。像

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

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


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

假设在重载解析之前检查了access,并且您使用了一个库和该库中的某个成员函数。然后,库作者将函数设置为私有函数。突然,您的代码开始使用不同的重载,并以完全不同的方式运行。库作者可能打算让任何使用该函数重载的人停止使用它,但他们并不打算更改每个人的代码。但是,随着标准的实际定义,您的代码现在将开始为您提供使用私有成员的错误,而不是行为不同


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

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

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

#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 
}
作为一个人为的例子,这里有一个非常糟糕的类接口:

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)
函数被公开,而第一个函数被删除,那么该代码会突然以完全不同的目的无声地调用另一个函数。当前规则防止访问说明符的改变,改变编译程序的行为。

< P>这是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 
}
#包括
福班{
公众:
const void bar()const{std::cout void Foo::bar()受保护
const_cast(c1.bar();//很好
}