为啥这个 const auto 变量在 range-for 循环中为类的 const 成员函数编译?
Posted
技术标签:
【中文标题】为啥这个 const auto 变量在 range-for 循环中为类的 const 成员函数编译?【英文标题】:Why is this const auto variable in a range-for loop compiling for a const member function of a class?为什么这个 const auto 变量在 range-for 循环中为类的 const 成员函数编译? 【发布时间】:2020-04-15 03:04:39 【问题描述】:我有以下类声明,根据我所学的有关 const 成员函数的知识,const 对象不能调用非 const 成员函数。在 range-for 循环中,我们使用的是“const auto animal”,假设它使用的是 const 对象,所以我认为 const 对象在调用非 const 成员函数 speak() 时应该会给出编译错误,但它实际编译,为什么?,也许我不清楚 range-for 循环是如何工作的......谢谢!
#include <iostream>
#include <string>
class Animal
protected:
std::string name_;
std::string speak_;
public:
Animal(const std::string &name, const std::string &speak) : name_(name), speak_(speak)
const std::string &getName() const return name_;
std::string speak() return speak_;
;
class Cat : public Animal
public:
Cat(const std::string &name) : Animal(name, "meow")
;
class Dog : public Animal
public:
Dog( const std::string &name) : Animal(name, "woof")
;
int main()
Cat tom "tom" ;
Dog felix "felix" ;
Animal *animals[] &tom, &felix;
for (const auto &animal : animals)
std::cout << animal->getName() << " says " << animal->speak() << '\n';
return 0;
【问题讨论】:
所有的魔法都在auto
之下。如果您尝试在其中打开,您会看到这是对常量指针的引用,而不是对常量指针的引用。这就是为什么你可以调用 Animal
的非 const 方法
【参考方案1】:
这里的const auto&
变成了对Animal*
类型变量的常量引用。这意味着您无法更改指针指向的位置,但指向的值本身仍然是可变的。
替换 auto 如下所示:
for (Animal* const& animal : animals)
// ...
【讨论】:
嗨!谢谢,这回答了我的问题,但它提出了另一个问题......你怎么能舒尔,或者你怎么知道这是“自动”正在采取的形式(除了它以这种方式工作的事实)。我的意思是,我也可以认为 auto 正在考虑(const Animal *animal)......这实际上是我发布这个问题的原因 @fespin 您可以使用static_assert(std::is_same_v<decltype(animal), Animal *const &>);
进行验证。还有一些特定于编译器的方法来打印变量的类型,例如coliru.stacked-crooked.com/a/8b6d0e588c0eb0cb
您要循环的整个类型是Animal*
。然后,auto
变成了Animal*
,我们在其中添加了一个 const 引用。一种考虑方法是将Animal*
替换为using animal_ptr = Animal*
;然后,const auto&
变为 const animal_ptr&
:也就是说,指针是 const,而不是内部发生的任何内容。
在您想到const Animal*
时,const
会以某种方式需要在内部指针中移动;也就是说,它需要进入animal_ptr
。另一方面,Animal* const
是正确的。 (请记住,const
适用于其左侧的内容,除非左侧没有任何内容,然后它直接应用于右侧的内容。)以上是关于为啥这个 const auto 变量在 range-for 循环中为类的 const 成员函数编译?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 lambda auto& 参数选择 const 重载?
C语言中auto,register,static,const,volatile的区别