从一个模板类转换为另一个(都派生自同一个基类)

Posted

技术标签:

【中文标题】从一个模板类转换为另一个(都派生自同一个基类)【英文标题】:Converting from one template class to another (both derived from the same base class) 【发布时间】:2015-12-09 17:25:57 【问题描述】:

我四处寻找,但找不到我的问题的答案。一段时间以来,我一直在尝试使转换构造函数在我的派生类中工作,但无论我做什么都无法使其工作。

为了简单起见,我有一个抽象基类和两个(很快会更多)派生类,它们都使用模板(它们是向量,因此它们使用模板来接受一种以上类型的元素)。一个是向量,其大小由模板参数决定,另一个大小取决于用于创建对象的参数。

我希望能够使用转换构造函数从一个转换为另一个。这是两个类的声明。我认为我应该跳过这些函数的实现,因为它们很长而且我认为与问题无关,但如果你认为有必要,我会将其添加到其余部分。

这是动态矢量类

template <class elem>
class Vect_variable : public Vect<elem>

    template <class T>
        friend std::ostream& operator<< (std::ostream&, const Vect_variable<T>&);

    template <class T>
        friend Vect_variable<T>& operator+ (T, const Vect_variable<T>&);
        // Pour les operations x+vecteur et pas vecteur+x avec int x

    template <class T>
        friend Vect_variable<T>& operator- (T, const Vect_variable<T>&);
        // Pour les operations x+vecteur et pas vecteur+x avec int x

    template <class T>
        friend Vect_variable<T>& operator* (T, const Vect_variable<T>&);
        // Pour les operations x+vecteur et pas vecteur+x avec int x

    public:
        Vect_variable(std::size_t sz = 0): taille(sz), vecteur(new elem[sz]) ;
        Vect_variable(std::size_t, const elem&);
        Vect_variable(const Vect_variable&);
        Vect_variable(Vect_variable&&);
        Vect_variable& operator=(const Vect_variable&);
        virtual elem& operator[] (std::ptrdiff_t nIndex);
        virtual const elem& operator[] (std::ptrdiff_t nIndex) const;
        virtual Vect_variable& operator+(); // + unaire
        virtual Vect_variable& operator-(); // - unaire
        virtual Vect_variable& operator+(const elem&); // + compos. par compos.
        virtual Vect_variable& operator-(const elem&); // - compos. par compos.
        virtual Vect_variable& operator*(const elem&); // * compos. par compos.
        virtual Vect_variable& operator+=(const elem&); // + compos. par compos.
        virtual Vect_variable& operator-=(const elem&); // - compos. par compos.
        virtual Vect_variable& operator*=(const elem&); // * compos. par compos.
        Vect_variable& operator+(const Vect_variable&); // + vect dynam.
        Vect_variable& operator-(const Vect_variable&); // - vect dynam.
        Vect_variable& operator*(const Vect_variable&); // * vect dynam.
        Vect_variable& operator+=(const Vect_variable&); // + vect dynam.
        Vect_variable& operator-=(const Vect_variable&); // - vect dynam.
        Vect_variable& operator*=(const Vect_variable&); // * vect dynam.
        ~Vect_variable () delete[] vecteur ;

    private:
        elem* vecteur;
        std::size_t taille;
;

这是由模板参数固定大小的向量

template <class elem, std::size_t taille=10>

class Vect_fixe: public Vect<elem>

    template <class T, std::size_t D>
        friend std::ostream& operator<< (std::ostream&, const Vect_fixe<T, D>&);

    template <class T, std::size_t D>
        friend Vect_fixe<T,D>& operator+ (T, const Vect_fixe<T, D>&);
        // Pour les operations x+vecteur et pas vecteur+x avec int x

    template <class T, std::size_t D>
        friend Vect_fixe<T,D>& operator- (T, const Vect_fixe<T, D>&);
        // Pour les operations x+vecteur et pas vecteur+x avec int x

    template <class T, std::size_t D>
        friend Vect_fixe<T,D>& operator* (T, const Vect_fixe<T, D>&);
        // Pour les operations x+vecteur et pas vecteur+x avec int x


    public:
        Vect_fixe() = default;
        Vect_fixe(const elem&);
        virtual elem& operator[] (std::ptrdiff_t nIndex);
        virtual const elem& operator[] (std::ptrdiff_t nIndex) const;
        virtual Vect_fixe& operator+() ; // + unaire
        virtual Vect_fixe& operator-(); // - unaire
        virtual Vect_fixe& operator+(const elem&); // + compos. par compos.
        virtual Vect_fixe& operator-(const elem&); // - compos. par compos.
        virtual Vect_fixe& operator*(const elem&); // * compos. par compos.
        virtual Vect_fixe& operator+=(const elem&); // + compos. par compos.
        virtual Vect_fixe& operator-=(const elem&); // - compos. par compos.
        virtual Vect_fixe& operator*=(const elem&); // * compos. par compos.
        Vect_fixe& operator+(const Vect_fixe&); // + vecteur meme taille
        Vect_fixe& operator-(const Vect_fixe&); // - vecteur meme taille
        Vect_fixe& operator*(const Vect_fixe&); // * vecteur meme taille
        Vect_fixe& operator+=(const Vect_fixe&); // + vecteur meme taille
        Vect_fixe& operator-=(const Vect_fixe&); // - vecteur meme taille
        Vect_fixe& operator*=(const Vect_fixe&); // * vecteur meme taille

        std::size_t get_size();
        elem get_vecteur();

    private:
        elem vecteur[taille] = 0;
        std::size_t size = taille;

;

所以我尝试使用带有另一个类类型参数的构造函数,但这似乎不起作用,因为其他类的一些模板参数没有声明(?),如果我声明它们它只是一直说无效的模板参数。我玩弄了很多,但我找不到正确的方法。缺乏对互联网的广泛了解(或者可能是我自己的研究能力不足),但我被困住了。

无论如何,这背后的一般想法是使用类似的东西:

Vect_variable(Vect_fixe<elem, taille>)

或者最终以任何其他方式从一种类型转换为另一种类型。

【问题讨论】:

前向声明是你的朋友。 @RichardHodges 你的意思是在定义之前声明?是的,他们确实如此。很抱歉,如果我变得稠密,但这对我的转换有帮助吗? 添加了一个完整的可编译示例作为答案。 【参考方案1】:

前向声明,可能需要两级:

#include <cstdint>

template<class Elem>
struct base


;

// forward declare classes
template<class Elem> struct variable;
template<class Elem, size_t N> struct fixed;

//forward declare members
template<class Elem> struct variable : base<Elem>

    variable() = default;
    template<size_t N> variable(const fixed<Elem, N>& r);

    variable& operator += (const variable& r);

    template<size_t N>
    variable& operator += (const fixed<Elem, N>& r);

;

template<class Elem, size_t N> struct fixed : base<Elem>

    fixed() = default;

;

// define members

template<class Elem>
template<size_t N>
variable<Elem>::variable(const fixed<Elem, N>& r)

    // implementation here


template<class Elem>
auto variable<Elem>::operator += (const variable& r) -> variable&

    // implementation here
    return *this;


template<class Elem>
template<size_t N>
auto  variable<Elem>::operator += (const fixed<Elem, N>& r) -> variable&

    // implementation here
    return *this;



using namespace std;

auto main() -> int

    fixed<double, 10> fd;
    variable<double> vd(fd);

    vd += fd;

    return 0;

【讨论】:

非常感谢!这确实与我尝试做的完全不同。 @DefinitelyNotMe 只是最后一件事......不要这样做。您实际上是在复制已经作为关键字存在的 const 和 mutable 的角色。这是不必要的。 “fixed_vector”只是一个“const variable_vector”。 嗯,我一开始就是这么想的,但我没有太多选择,因为这是一个更大项目的一部分,显然两者都需要。未来拥有我想的答案。 告诉你的首席开发者我祝他好运:-) 很抱歉,只是一个小问题。在您的实现中,固定类和可变类都使用相同的模板,但在我的情况下,其中一个模板有一个附加参数(定义了固定向量的大小),当我尝试声明时,该参数未声明构造函数。有没有办法解决这个问题?编辑-他是我的老师 :D 然后我会在我的 cmets 的某个地方添加它【参考方案2】:

我看不到将Vect_variable 转换为Vect_fixe 的方法,后者要求大小是模板参数(在编译时保持不变),但获得大小的唯一方法Vect_variable 在运行时。

但我没有看到从Vect_fixe 转换为Vect_variable 的任何特殊问题:

template<std::size_t size> Vect_variable(const Vect_fixe<elem,size>& other) : Vect_variable(size)
 
  for (int i = 0; i < size; ++i)
  
    (*this)[i] = other[i];
  

【讨论】:

可能是我对模板的理解不够深入,但是用不同的模板参数创建一个对象不是很像吗?固定向量的大小可以更改,它只是使用模板创建对象时必须提供的参数的一部分。使用转换时不一样吗?只是给模板变量向量的大小作为参数。

以上是关于从一个模板类转换为另一个(都派生自同一个基类)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C++ 中的模板编程从基类创建派生类?

派生类模板看不到基类的成员[重复]

将“typedef”从“模板”的基类传播到派生类

c++ 模板化抽象基类数组,不违反严格别名规则

C++ 派生模板类:访问实例的受保护成员

派生类中类模板的部分特化会影响基类