当 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方法是公共的,因此用户可以查询vector。非const方法是受保护的,所以我可以用它来修改我需要的数据。
但是,当我尝试使用类并调用get方法时,编译器报错非const方法受到保护。相反,我必须使用const_cast将对象强制转换为const,这样我就可以获得公共方法。
有办法解决这个问题吗?既然有一个公共方法,为什么编译器不自己进行强制类型转换呢?如果我删除受保护的版本,只留下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。像
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强制转换,这将导致调用方法的const版本。
#include <iostream>
class Foo {
public:
const void bar() const { std::cout << " const version calledn";}
protected:
void bar() { std::cout << " non const version calledn";}
};
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 对象访问非 const 方法
- 为什么我可以调用一个从const方法更改成员的方法
- 使用新的c++返回值语法的Const方法
- const_cast const 方法中的"this"将"this"分配给外部变量?
- const 方法使用引用修改对象
- 从具有相同基数的另一个派生类调用派生类的非 const 方法
- 返回非常量引用编译的 Const 方法
- C++:无法从 const 方法返回对象的shared_ptr
- 是否可以从 const 方法迭代链表
- 为什么在const和非const方法中删除代码重复不是不确定的行为
- 在使用指向 const 和非 const 方法的成员指针时减少模板专用化的数量
- "可变"变量只能由 const 方法之一可变?
- Golang中的const方法
- C++ 逻辑恒常性和 const方法的按值返回
- c++将标志添加到const方法中
- C++防止const方法通过成员指针或引用更改数据
- 为什么 const 方法不覆盖 C++ 中的非 const 方法?
- 如何在const方法中迭代映射
- 为什么没有标准化的方法来避免const方法的代码重复
- 修改 const 方法中的 pointee 值