【问题标题】: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 方法

标签: c++ c++11 constants auto for-range


【解决方案1】:

这里的const auto&amp; 变成了对Animal* 类型变量的常量引用。这意味着您无法更改指针指向的位置,但指向的值本身仍然是可变的。

替换 auto 如下所示:

for (Animal* const& animal : animals)
  // ...

【讨论】:

  • 嗨!谢谢,这回答了我的问题,但它提出了另一个问题......你怎么能舒尔,或者你怎么知道这是“自动”正在采取的形式(除了它以这种方式工作的事实)。我的意思是,我也可以认为 auto 正在考虑(const Animal *animal)......这实际上是我发布这个问题的原因
  • @fespin 您可以使用static_assert(std::is_same_v&lt;decltype(animal), Animal *const &amp;&gt;); 进行验证。还有一些特定于编译器的方法来打印变量的类型,例如coliru.stacked-crooked.com/a/8b6d0e588c0eb0cb
  • 您要循环的整个类型是Animal*。然后,auto 变成了Animal*,我们在其中添加了一个 const 引用。一种考虑方法是将Animal* 替换为using animal_ptr = Animal*;然后,const auto&amp; 变为 const animal_ptr&amp;:也就是说,指针是 const,而不是内部发生的任何内容。
  • 在您想到const Animal* 时,const 会以某种方式需要在内部指针中移动;也就是说,它需要进入animal_ptr。另一方面,Animal* const 是正确的。 (请记住,const 适用于其左侧的内容,除非左侧没有任何内容,然后它直接应用于右侧的内容。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-27
  • 2020-09-29
  • 1970-01-01
  • 1970-01-01
  • 2017-03-01
  • 1970-01-01
相关资源
最近更新 更多