很抱歉有大量的源代码。有三个抽象类P,L,PL。第三类PL使用虚拟继承从类P和L派生:
template <typename T> //Abstract class
class P
{
public:
virtual ~P() = 0;
virtual P <T> *clone() const = 0;
};
template <typename T>
P<T>::~P() {}
template <typename T>
P<T> * P <T>:: clone() const { return new P <T> ( *this ); }
template <typename T> //Abstract class
class L
{
public:
virtual ~L() = 0;
virtual L <T> *clone() const = 0;
};
template <typename T>
L<T>::~L() {}
template <typename T>
L<T> *L <T> ::clone() const { return new L <T> ( *this );}
template <typename T>
class PL: virtual public P <T>, virtual public L <T> //Abstract class
{
public:
PL() : P <T>(), L<T>() {}
virtual ~PL() = 0;
virtual PL <T> *clone() const = 0;
};
template <typename T>
PL<T>::~PL() {}
template <typename T>
PL<T> * PL <T> :: clone() const { return new PL <T> ( *this );}
每个类都有自己的克隆方法实现。
下一个类PA,PC是使用虚拟继承从类P派生的:
template <typename T>
class PC : virtual public P <T>
{
public:
PC() : P <T> () {}
virtual ~PC() {}
virtual PC <T> *clone() const {return new PC <T> ( *this );}
};
template <typename T>
class PA : virtual public P <T>
{
public:
PA() : P <T> () {}
virtual ~PA() {}
virtual PA <T> *clone() const {return new PA <T> ( *this );}
};
最后两个类PCL和PAL是使用PC和PL,PA和PL的虚拟继承进行的。
template <typename T>
class PCL : public PC <T>, public PL <T>
{
public:
PCL() : P <T> (), PC <T> (), PL <T> () {}
virtual ~PCL() {}
virtual PCL <T> *clone() const {return new PCL <T> ( *this );}
};
template <typename T>
class PAL : public PA <T>, public PL <T>
{
public:
PAL() : P <T> (), PA <T> (), PL <T> () {}
virtual ~PAL() {}
virtual PAL <T> *clone() const {return new PAL <T> ( *this );}
};
有类依赖关系图:
.......... P .... L.....
........../|\..../......
........./.|.\../.......
......../..|..\/........
.......PC..PA..PL.......
.......|...|.../|.......
.......|...|../.|.......
.......|...PAL..|.......
.......|........|.......
.......PCL_____/........
请不要讨论这个提议:-)))。我有以下3个问题:
1)这个类依赖是否正确地在C ++中重写(首先是“虚拟”的位置)?
2)我不确定有什么问题,请看代码:
int main(int argc, _TCHAR* argv[])
{
PCL <double> * pcl = new PCL <double>(); //Object of abstract class not allowed
PAL <double> * pal = new PAL <double>(); //Object of abstract class not allowed
PL <double> *pl1 = pcl->clone(); //Polymorphism
PL <double> *pl2 = pal->clone(); //Polymorphism
return 0;
}
无法创建PAL / PCL类的新对象,这两个类都标记为抽象。但它们并不是抽象的。问题在哪里?
3)是否可以将多态与clone()方法一起使用?请参阅上面的代码,请...
感谢您的帮助......
更新的问题
我更正了代码。但是使用VS 2010编译器出现以下错误:
template <typename T> //Abstract class
class P
{
public:
virtual ~P() = 0;
virtual P <T> *clone() const = 0;
};
template <typename T>
P<T>::~P() {}
template <typename T>
P<T> * P <T>:: clone() const { return new P <T> ( *this ); }
template <typename T> //Abstract class
class L
{
public:
virtual ~L() = 0;
virtual L <T> *clone() const = 0;
};
template <typename T>
L<T>::~L() {}
template <typename T>
L<T> *L <T> ::clone() const { return new L <T> ( *this );}
template <typename T>
class PL: virtual public P <T>, virtual public L <T> //Abstract class
{
public:
PL() : P <T>(), L<T>() {}
virtual ~PL() = 0;
virtual PL <T> *clone() const = 0;
};
template <typename T>
PL<T>::~PL() {}
template <typename T>
PL<T> * PL <T> :: clone() const { return new PL <T> ( *this );}
template <typename T>
class PC : virtual public P <T>
{
protected:
T pc;
public:
PC() : P <T> () {}
virtual ~PC() {}
virtual PC <T> *clone() const {return new PC <T> ( *this );}
};
template <typename T>
class PA : virtual public P <T>
{
public:
PA() : P <T> () {}
virtual ~PA() {}
virtual PA <T> *clone() const {return new PA <T> ( *this );}
};
template <typename T>
class PCL : public PC <T>, public PL <T>
{
public:
PCL() : P <T> (), PC <T> (), PL <T> () {}
virtual ~PCL() {}
virtual PCL <T> *clone() const {return new PCL <T> ( *this );}
}; //Error using VS 2010: Error 1 error C2250: 'PCL<T>' : ambiguous inheritance of 'PC<T> *P<T>::clone(void) const'
template <typename T>
class PAL : public PA <T>, public PL <T>
{
public:
PAL() : P <T> (), PA <T> (), PL <T> () {}
virtual ~PAL() {}
virtual PAL <T> *clone() const {return new PAL <T> ( *this );}
}; //Error VS 2010: Error 1 error C2250: 'PAL<T>' : ambiguous inheritance of 'PA<T> *P<T>::clone(void) const'
int main(int argc, char* argv[])
{
PCL <double> * pcl = new PCL <double>();
PAL <double> * pal = new PAL <double>();
PL <double> *pl1 = pcl->clone();
PL <double> *pl2 = pal->clone();
return 0;
}
也许我忽略了一些东西......但是g ++编译好这段代码。
答案 0 :(得分:3)
代码中只有一些小错误:
正确获取基本初始值设定项: [抱歉,这是错误的 - 你做因为虚拟继承而必须调用虚拟基础构造函数。]你必须说圆括号。PAL() : PC <T>(), PL <T>() {}
P<T>
没有初始化,这不是直接基础;但
在没有定义的情况下声明纯虚函数:virtual L <T> *clone() const = 0;
仔细检查您希望PL
从P
虚拟地继承,但是从L
非虚拟地继承(但没关系)。
仔细检查所有clone()
是否具有相同的常量。
如果您的抽象基类中已经有一个纯虚函数,则不应该使析构函数为纯。相反,比方说,virtual ~T() { }
。否则你仍然应该提供纯虚析构函数的定义(因为析构函数总是需要可调用):virtual T::~T() { }
答案 1 :(得分:2)
MSVC不能正确支持共变体返回。你认为你已经超越了这个功能的地方,实际上你一直在隐藏它。这就是手头的问题。
答案 2 :(得分:1)
这使用VC10为我编译:
template <typename T> //Abstract class
class P
{
public:
virtual ~P() = 0;
virtual P <T> *clone() const = 0;
};
template <typename T>
P<T>::~P() {}
template <typename T> //Abstract class
class L
{
public:
virtual ~L() = 0;
virtual L <T> *clone() const = 0;
};
template <typename T>
L<T>::~L() {}
template <typename T>
class PL: virtual public P <T>, virtual public L <T> //Abstract class
{
public:
PL() : P <T>(), L<T>() {}
virtual ~PL() = 0;
// virtual PL <T> *clone() const = 0; // REMOVED!
};
template <typename T>
PL<T>::~PL() {}
template <typename T>
class PC : virtual public P <T>
{
protected:
T pc;
public:
PC() : P <T> () {}
virtual ~PC() {}
virtual PC <T> *clone() const {return new PC <T> ( *this );}
};
template <typename T>
class PA : virtual public P <T>
{
public:
PA() : P <T> () {}
virtual ~PA() {}
virtual PA <T> *clone() const {return new PA <T> ( *this );}
};
template <typename T>
class PCL : public PC <T>, public PL <T>
{
public:
PCL() : P <T> (), PC <T> (), PL <T> () {}
virtual ~PCL() {}
virtual PCL <T> *clone() const {return new PCL <T> ( *this );}
};
template <typename T>
class PAL : public PA <T>, public PL <T>
{
public:
PAL() : P <T> (), PA <T> (), PL <T> () {}
virtual ~PAL() {}
virtual PAL <T> *clone() const {return new PAL <T> ( *this );}
};
int main()
{
PCL <double> * pcl = new PCL <double>();
PAL <double> * pal = new PAL <double>();
PL <double> *pl1 = pcl->clone();
PL <double> *pl2 = pal->clone();
return 0;
}
请注意,我必须删除PL <T> *PL <T>::clone()
才能让VC接受代码。问题是,如果您有一个PL<T>
,并将其称为clone()
,它将静态返回L<T>*
,而不是PL<T>*
,即使动态type是从PL<T>
派生的类。
答案 3 :(得分:0)
因为P类中的clone方法是定义的抽象
virtual P <T> *clone() const = 0 {};
(顺便说一句{}不正确)。您必须了解的是,一旦实例化此模板,这是一个单独的方法,其中包含与derive类clone方法完全不同的签名。模板实例化创建的行为就像它生成新代码一样。因此,这是一个从未实现的纯抽象方法。从而使每个继承此方法(每个派生类)的人都成为一个抽象类。
编辑:至于第三个问题。运行时和编译时多态性不能很好地混合。我不知道为什么你想要使用如此复杂的结构,但我确信设计可以简化得更远。
答案 4 :(得分:0)
在您的代码中有一些需要修复的拼写错误,但是
继承点阵中的virtual
是正确的。 (他们是
最小。你可以添加更多;在极少数情况下这种格子
发生,通常最好使所有继承虚拟,以保护
反对未来的进化。)
您的测试代码没有任何问题。一旦打字错误了 原文是固定的,用g ++编译好。
这是可能的,它应该按照你的方式工作。