每当我尝试编译代码时,我都会无效使用auto。来自Java背景,我不确定我是否完全理解C ++模板。似乎编译器可以推断出类型。我仅限于C ++ 11。
GeneralRenderer中发生错误。
动物类
class Animal {};
class Dog : public Animal {};
class Cat : public Animal {};
enum AnimalType {
Dog,
Cat
};
渲染课程
template<class T>
class AnimalRenderer {
virtual void draw(T entity) = 0;
};
class DogRenderer : public AnimalRenderer<Dog> {};
class CatRenderer : public AnimalRenderer<Cat> {};
逻辑
class GeneralRenderer {
public:
void draw(
std::map<AnimalType, std::vector<Animal>> animalMap) {
for (auto entry: animalMap) {
AnimalRenderer<auto> renderer; // <--- Causes the error
switch (entry.first) {
case Dog:
renderer = DogRenderer();
break;
case Cat:
renderer = CatRenderer();
break;
}
for (auto animal: entry.second) {
renderer.draw(entry);
}
}
};
};
答案 0 :(得分:8)
非正式地说,auto
可以用于同时声明和初始化类型。然后编译器可以从用于初始化变量的值推断出类型。
但事实并非如此;像
这样的陈述auto n;
也会失败。
请注意,auto
仅代表在编译时已知的类型。在那里使代码更具可读性,尽管它的使用偶尔也是强制性的,例如在使用lambda函数时。 不是变体类型构造cf. std::variant
说C ++ 17。
最后请注意,std::map
与java.util.Map
是完全不同的野兽。 C ++中没有类型擦除,因此如果std::map<A, B>
与std::map<C, D>
不同,A
与C
的根本不同类型}和/或B
与D
不同。此外,C ++允许您在地图中存储值类型。
答案 1 :(得分:1)
正如其他用户已经说过的那样,没有右手变量,auto就无法工作。
我认为您应该从AnimalRenderer中删除模板注释,然后您可以正常使用这些类。
答案 2 :(得分:1)
要获得您想要的结果,您需要在案例中移动第二个for循环,其中可以针对每种情况解决扣除。
您不希望代码重复,因此理想情况下您需要一个模板函数,您可以调用它来执行第二个循环。在最新的c ++标准中,您也可以声明模板lambda函数。
那就是说,在架构上,我建议为AnimalRenderer添加一个接口基类,然后你可以声明一个指向该基类的简单指针,特别是当你已经将draw声明为虚拟时。