模板函数内部开关状态情况下的不同类型分配

2024-01-08

Apple.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 与 Apple 相同

存储.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;
}

main.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;
}

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


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

解决这个问题的一种方法是使用重载而不是函数模板 as (这意味着,不需要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)帮助编译器根据以下内容选择正确的重载type表达式的static_cast<FoodType*>(0)这将是任一类型Apple* or Potato*.


@Gorpik 评论里说 https://stackoverflow.com/a/11035109/415784两者(这个以及其他解决方案)都很丑陋,所以这是解决这个问题的另一种尝试。

定义一个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();
        }
};

该基类存储以下食品one仅键入,但在问题中,我们需要存储以下食品two类型。因此,为了做到这一点,我们定义另一个类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();
        }
};

这里要注意两点:

  • 班上storage现在没有任何会员数据。它只是将调用转发到根据模板参数的类型选择的基类FoodType.
  • 由此衍生出私下里来自基类。所以它不是is-a关系。

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

这个解决方案的优点在于,如果你想让它工作three食物类型,那么你需要从中获取它three基类为:

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

     //same as before; no change at all !

};

Demo : http://ideone.com/lnMds http://ideone.com/lnMds

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

模板函数内部开关状态情况下的不同类型分配 的相关文章

随机推荐