【问题标题】:How to interpret A<B<T>>* as A<C<T>>* where B : public C<T>?如何将 A<B<T>>* 解释为 A<C<T>>* where B : public C<T>?
【发布时间】:2020-05-18 08:43:07
【问题描述】:

考虑一个包含以下代码的文件 main.cc:

template<typename Commodity>
class Shop
{
public:
    Shop(){}
    ~Shop(){}
};

template<typename FuelType>
class Car
{
public:
    Car(){}
    virtual ~Car(){}
};

template<typename FuelType>
class Volkswagen : public Car<FuelType>
{
public:
    Volkswagen(){}
    ~Volkswagen(){}
};

int main()
{   
    // this is fine...
    Car<int>* myCar = new Volkswagen<int>();

    delete myCar;

    // ...but this isn't
    Shop<Car<int>>* myCarShop = new Shop<Volkswagen<int>>();

    return 0;
}

当我尝试编译时,我得到一个错误:

cannot convert 'Shop<Volkswagen<int> >*' to 'Shop<Car<int> >*' in initialization...'

现在,我明白了为什么会出现此错误。这是因为Shop&lt;Volkswagen&lt;T&gt;&gt; 通常不必从Shop&lt;Car&lt;T&gt;&gt; 继承。

我的问题是:如何实现这样的结构?有没有更好的类和模板方法,或者当我绝对确定Shop&lt;Volkswagen&lt;T&gt;&gt; 始终是Shop&lt;Car&lt;T&gt;&gt; 时,我应该尝试显式转换指针吗?

编辑 1:一种解决方案可能是添加一个类

template<typename FuelType>
class VolkswagenShop : public Shop<Volkswagen<FuelType>>, public virtual Shop<Car<FuelType>>
{
public:
  VolkswagenShop(){}
  ~VolkswagenShop(){}
};

然后写

Shop<Car<int>>* myCarShop = new VolkswagenShop<int>();

这可以编译,但是结构已经变得复杂到我以我非常有限的 c++ 能力,不确定这是否会导致任何问题。

那么,冒着过于模糊的风险,上述解决方案会导致任何明显的问题吗?

【问题讨论】:

  • Shop&lt;Volkswagen&lt;T&gt;&gt;Shop&lt;Car&lt;T&gt;&gt; 是不同且不相关的类型。但是你可以让Shop 在内部管理一个Car 指针。
  • 即使 TU 相关,你也不能在 c++ 中 Shop&lt;T&gt;Shop&lt;U&gt; 是完全独立的类
  • 我知道这只是一个例子,但为什么CarVolkswagen 必须是模板?
  • @PaulSanders 模仿我遇到这个问题的更大项目的结构
  • 我不完全理解您尝试的解决方案。从Shop&lt;Car&lt;T&gt;&gt; 继承Shop&lt;Volkswagen&lt;T&gt;&gt; 会是一个解决方案吗?看起来这就是你想要的

标签: c++ c++11 templates inheritance polymorphism


【解决方案1】:

模板实例化不是继承! foo&lt;A&gt;foo&lt;B&gt; 是两种截然不同且不相关的类型。如果您希望所有 Shop&lt;CARTYPE&lt;T&gt;&gt; 都继承自 Shop&lt;Car&lt;T&gt;&gt;,那么您可以这样做。

如果可以将Shop 的声明更改为采用 2 个模板参数(并且如果您不害怕模板模板参数),您可以这样做:

template<typename FuelType>
class Car
{
public:
    Car(){}
    virtual ~Car(){}
};

template<typename FuelType>
class Volkswagen : public Car<FuelType>
{
public:
    Volkswagen(){}
    ~Volkswagen(){}
};

template <template<class> class CarType,typename Commodity>
class Shop : public Shop<Car,Commodity>
{
public:
    using Car_t = CarType<Commodity>;
    Shop(){}
    virtual ~Shop(){}
};

template <typename Commodity>
class Shop<Car,Commodity> {
    virtual ~Shop(){}
};


int main()
{   
    // this is fine...
    Car<int>* myCar = new Volkswagen<int>();
    delete myCar;
    // this also
    Shop<Car,int>* myCarShop = new Shop<Volkswagen,int>();
    delete myCarShop;
    return 0;
}

然而,模板特化也不是继承!您将需要重复通用模板和template &lt;typename Commodity&gt; class Shop&lt;Car,Commodity&gt; {}; 专业化中的所有方法。为避免代码重复,您可以编写一个不是模板的ShopBase 类,并提供您希望在所有商店中以多态方式使用的接口。

PS:混合编译时间和运行时多态是可能的,但我会重新考虑你真正需要什么。看看CRTP 可能会给你一些启发。

【讨论】:

    猜你喜欢
    • 2012-07-29
    • 2018-01-12
    • 1970-01-01
    • 2019-02-01
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 2019-08-08
    相关资源
    最近更新 更多