gpt4 book ai didi

c++ - 开关状态案例中的不同类型分配,内部模板函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:25:58 29 4
gpt4 key购买 nike

苹果.h

class Apple {
public:
Apple(int);
static int typeID;
private:
int id_;
};

苹果.cpp

#include "Apple.h"
Apple::Apple(int pID) {
id_ = pID;
}

Potato.h, Potato.cpp 与苹果相同

存储.h

#pragma once
#include "Apple.h"
#include "Potato.h"
#include <vector>
class Storage {
public:
Storage();
template<typename foodName> void store(foodName * object){
(*getBasket<foodName>()).push_back(object);
};
template<typename foodName> int countSize(){
return (*getBasket<foodName>()).size();
};

private:
std::vector<Apple*> applebasket_;
std::vector<Potato*> potatobasket_;
template <typename foodName> std::vector<foodName*> * getBasket(){
std::vector<foodName*> * result;
switch(foodName::typeID){
case 0:
result = &applebasket_;
break;
case 1:
//result = &potatobasket_;
break;
}
return result;
}
};

存储.cpp

#include "Storage.h"
int Apple::typeID;
int Potato::typeID;
Storage::Storage() {
Apple::typeID = 0;
Potato::typeID =1;
}

主要.cpp

#include "Storage.h"
#include <iostream>
int main() {
Apple* apple;
Potato* potato;
Storage storage;
int i;
for(i = 0;i < 7;i++){
apple = new Apple(i);
storage.store<Apple>(apple);
}
std::cout<<storage.countSize<Apple>();
return 0;
}

此代码有效并输出正确大小的 vector ,但如果 switch 语句(在 Storage.h 内)中的 case 行未注释,则编译器 (g++) 会抛出“错误:无法在赋值中将‘std::vector < Potato*>* '转换为‘std::vector< Apple*>* '”。这就像编译器无论如何都要尝试这两种情况,我无法找到是否有可能以及如何避免这种情况。我需要这方面的帮助,也许还有一些关于整个事情的建议(不同类型容器的一个接口(interface)),我最近开始学习 C++,我在这里尝试这样做的方式可能一团糟。

最佳答案

您的代码无法编译,因为 case应该编译这是不可能的,因为类型在 case 中不同。 .

这个问题的一个解决方案是使用重载而不是函数模板(这意味着,在你的类中不需要 typeID!):

std::vector<Apple*> * get_basket(Apple *)
{
return &applebasket_; //return pointer to the apple basket
}

std::vector<Potato*> * get_basket(Potato *)
{
return &potatobasket_; //return pointer to the potate basket
}

并将其命名为:

template<typename FoodType> 
void store(FoodType * object)
{
std::vector<FoodType> * basket = get_basket(static_cast<FoodType*>(0));
basket->push_back(object);
}

这里的技巧是你有两个重载,每个都有一个不同类型的参数,所以你使用static_cast<FoodType*>(0)帮助编译器根据表达式 static_cast<FoodType*>(0)类型 选择正确的重载这将是 Apple* 类型之一或 Potato* .


@Gorpik said in the comment两者(这个以及其他解决方案)都很丑陋,所以这是解决这个问题的另一种尝试。

定义一个 base_storage类模板为:

template<typename FoodType>
class base_storage
{
std::vector<FoodType*> m_storage;
public:
void store(FoodType *foodItem)
{
m_storage.push_back(foodItem);
}
size_t count() const
{
return m_storage.size();
}
};

此基类仅存储一种 类型的食品,但在问题中,我们需要存储两种 类型的食品。所以为了做到这一点,让我们定义另一个类 Storage从上述类模板派生为:

class storage : private base_storage<Apple>, private base_storage<Potato>
{
public:
template<typename FoodType>
void store(FoodType * foodItem)
{
base_storage<FoodType>::store(foodItem);
}
template<typename FoodType>
size_t count() const
{
return base_storage<FoodType>::count();
}
};

这里注意两点:

  • 类(class) storage现在没有任何成员(member)数据。它只是将调用转发给根据模板参数类型选择的基类 FoodType .
  • 它从基类私下派生。所以它不是is-a关系。

请在此处查看此解决方案的在线演示:http://ideone.com/Ykjo5

这个解决方案的美妙之处在于,如果你想让它适用于三种 类型的食物,那么你只需要从三个 基类派生它,如下所示:

class storage : private base_storage<Apple>, 
private base_storage<Potato>,
private base_storage<Mango> //added line!
{

//same as before; no change at all !

};

演示:http://ideone.com/lnMds

关于c++ - 开关状态案例中的不同类型分配,内部模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11034759/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com