C++中的构造函数副本、列表、指针和模板

Constructor copy, list, pointers and template in C++

本文关键字:指针 列表 C++ 构造函数 副本      更新时间:2023-10-16

我想做一个复制构造函数,并为下面的类定义=运算符

template <class S, class T>
class Graphe
{
protected:
int prochaineClef;
public:
PElement< Sommet<T> > * lSommets; // liste de sommets
PElement< Arete<S,T> > * lAretes; // liste d'arêtes
Graphe(const Graphe<S,T> & graphe);
const Graphe<S,T> & operator = (const Graphe<S,T> & graphe);
}

到目前为止,我已经尝试过关于构造函数:

template <class S, class T>
Graphe<S,T>::Graphe(const Graphe<S,T> & graphe)
{
PElement< Sommet<T> > * nouvelListeSommet = new PElement<Sommet<T>>(*graphe.lSommets);
PElement< Arete<S,T> > * nouvelListeAretes = new PElement<Arete<S,T>>(*graphe.lAretes);
this->prochaineClef = graphe.prochaineClef;
this->lAretes = nouvelListelAretes;
this->lSommets = nouvelListeSommet;
//nouvelListeSommet = graphe.lSommets->copieListe(graphe.lSommets);
//nouvelListelAretes = graphe.lAretes->copieListe(graphe.lAretes);
}
So i got this error saying 
visual studio 2012projectsihmtp2graphetp2graphepelement.h(123): error C2664: 'PElement<T>::PElement(T *,PElement<T> *)' : can't convert param1 from 'PElement<T> *const ' to 'Sommet<T> *'
1>          with
1>          [
1>              T=Sommet<InfoSommetCarte>
1>          ]
1>          and
1>          [
1>              T=Sommet<InfoSommetCarte>
1>          ]
1>          and
1>          [
1>              T=InfoSommetCarte
1>          ]

这是我的PElement类:

class PElement
{
public :
T * v;
PElement<T> * s;

PElement( T * v, PElement<T> * s );
PElement(PElement<T> & l);
}
template<class T>
PElement<T>::PElement(PElement<T> & l)
{
    //this->v = new T(l->v);
    this = new PElement<T>(l,this);
}

我不知道如何修复我的复制构造函数PElement这个->v=新T(l->v)正确吗?

这是我的错误副本列表方法:

/*
template<class T>
PElement<T> * PElement<T>::copieListe(PElement<T> * original)
{
    for(int i = 0; i < PElement<T>::taille(original);i++)
    {
        this->insertionTete(original->v,this);
        original = original->s;
    }
    return this;
}
*/

如果列表不为空,则需要为PElement类复制一个复制初始值设定项,用于复制下一个元素。

template <class T>
class PElement
{
public :
    T * v;
    PElement<T> * s;
    PElement(T * v, PElement<T> * s = nullptr);
    PElement(const PElement<T> & l);
};
template<class T>
PElement<T>::PElement(T * v, PElement<T> * s) : v(v), s(s) {}
template<class T>
PElement<T>::PElement(const PElement<T> & l)
{
    v = new T(*l.v);
    s = l.s ? new PElement<T>(*l.s) : nullptr;
}

这就是图类的副本初始化器

template <class S, class T>
Graphe<S,T>::Graphe(const Graphe<S,T> & graphe)
{
    lSommets = graphe.lSommets ? new PElement<Sommet<T>>(*graphe.lSommets) : nullptr;
    lAretes = graphe.lAretes ? new PElement<Arete<S,T>>(*graphe.lAretes) : nullptr;
    prochaineClef = graphe.prochaineClef;
}

我不会用这种方式实现它,因为列表是递归复制的,如果列表很长,可能会出现堆栈溢出。按照@Rerito的建议,您应该使用std::list。这个代码示例向您展示了应该如何进行操作以避免出现错误。

PElement的复制构造函数需要对PElement进行引用。这就是我们传递*graphe.lSommets和*graphe.l Aretes.

的原因

表达式graphe.lSommets指针,并且没有PElement构造函数接受指针。

这可以通过创建一个接受指针的新构造函数来解决,或者(我建议的方式)取消引用指针:

new PElement<Sommet<T>>(*graphe.lSommets);
//                      ^
//                      |
// Note the dereference operator

以下PElement<T>的复制构造函数应该可以工作。

template <typename T>
PElement<T>::PElement(const PElement<T> &o) : v(nullptr), s(nullptr) {
    // I assume you are marking the end of the list by a nullptr sentinel
    if (nullptr != o.s) {
        s = new PElement<T>(*o.s);
    }
    // Two options for `v`, pick one...
    v = o.v; // Shallow copy of the T pointers
    v = new T(*o.v) // Deep copy of the T pointers... Assume T is copyable
}

它将递归地复制列表中的每个元素,并在点击nullptr sentinel时停止。

如果您想保持PElement的原样(使用T*来保存模板类型的东西),您可能需要执行深度复制(因此您选择this->v = new T(*o.v)),否则您可能会考虑按值存储在列表元素中。

然后,您可以在图形复制构造函数中使用它:

template <typename S, typename T>
Graphe<S,T>::Graphe(const Graphe<S,T> &g) {
    lSommets = new PElement<Sommet<T>>(*g.lSommets);
    lAretes = new PElements<Arete<S,T>>(*g.lAretes);
    // ... Whatever work you need ...
    prochaineClef = g.prochaineClef;
}