C++ 中的构造函数副本、列表、指针和模板
Constructor copy, list, pointers and template in C++
我想做一个复制构造函数并为此定义 = 运算符 class
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 2012\projects\ihm\tp2graphe\tp2graphe\pelement.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 :
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
this->v = new T(l->v) 正确吗?
这是我错误的 copieListe 方法:
/*
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;
}
*/
表达式 graphe.lSommets
是一个 指针 并且您没有 PElement
构造函数获取指针。
这可以通过创建一个接受指针的新构造函数或(我推荐的方式)取消引用指针来解决:
new PElement<Sommet<T>>(*graphe.lSommets);
// ^
// |
// Note the dereference operator
您需要 PElement class 的复制初始值设定项,如果列表不为空,它会复制下一个元素。
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;
}
这就是图的复制初始值设定项class
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.lAretes 的原因。
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
标记时停止。
如果你想保持 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;
}
我想做一个复制构造函数并为此定义 = 运算符 class
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 2012\projects\ihm\tp2graphe\tp2graphe\pelement.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 :
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 this->v = new T(l->v) 正确吗?
这是我错误的 copieListe 方法:
/*
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;
}
*/
表达式 graphe.lSommets
是一个 指针 并且您没有 PElement
构造函数获取指针。
这可以通过创建一个接受指针的新构造函数或(我推荐的方式)取消引用指针来解决:
new PElement<Sommet<T>>(*graphe.lSommets);
// ^
// |
// Note the dereference operator
您需要 PElement class 的复制初始值设定项,如果列表不为空,它会复制下一个元素。
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;
}
这就是图的复制初始值设定项class
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.lAretes 的原因。
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
标记时停止。
如果你想保持 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;
}