c++,虚拟继承,奇怪的抽象类+克隆问题
C++, virtual inheritance, strange abstract class + clone problem
很抱歉,源代码太多了。有三个抽象类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 );}
每个类都有自己的clone方法实现。
接下来的两个类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++中重写的类依赖是否正确(首先是"virtual"的位置)?
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()方法一起使用?请参阅上面的代码…
谢谢你的帮助…
<
更新问题/strong>
我更正了代码。但是使用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++可以编译这些代码
你的代码中有一些小错误:
得到正确的基初始化:[对不起,这是错误的——由于虚继承,必须调用虚基构造函数。你必须加上圆括号PAL() : PC <T>(), PL <T>() {}
没有初始化P<T>
,它不是直接基;但是声明没有定义的纯虚函数:
virtual L <T> *clone() const = 0;
仔细检查你想要
PL
从P
继承而不是从L
继承(但这很好)。仔细检查你所有的
clone()
具有相同的一致性如果在抽象基类中已经有一个纯虚函数,则不应该使析构函数为纯函数。而是说,
virtual ~T() { }
。否则,您仍然应该提供纯虚析构函数的定义(因为析构函数总是需要可调用的):virtual T::~T() { }
MSVC不支持协变返回。你认为你重写了函数,实际上你只是隐藏了它。
使用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>*
,即使动态类型是从PL<T>
派生的类。
因为p类中的clone方法在定义时是抽象的
virtual P <T> *clone() const = 0 {};
(顺便说一下{}是不正确的)。您必须理解的是,一旦这个模板被实例化,它就是一个独立的方法,具有与派生类克隆方法完全不同的签名。模板实例化创建的行为就像它生成新代码一样。因此,这是一个从未实现过的纯抽象方法。从而使每个继承此方法的人(每个派生类)都是抽象类。
编辑:至于第三个问题。运行时多态性和编译时多态性不能很好地混合在一起。我不知道你到底为什么要用这么复杂的结构,但我确信设计可以简化得更多。
有几个错字需要修复在你的代码,但继承格中的
virtual
s是正确的。(他们最小值。你可以添加更多;在很少的情况下,这样的格子发生时,通常最好将所有继承设置为虚拟,以进行保护你的测试代码没有问题。一旦出现错别字
这是可能的,它应该按照你所做的方式工作。
- 无法创建抽象类的实例
- 用pybind11包装C++抽象类时出错
- 如何处理从一个对象传递到另一个在C++中具有公共抽象类的对象的消息
- 有没有办法按值将纯抽象类的所有子类传递给 C++ 中的函数?
- 抽象类错误,请参阅声明" "是抽象的
- 将自定义函数传递到基抽象类中以延迟执行
- 将包含抽象类和普通类C++包导出到 Python
- C++:处理抽象类中的错误时出现问题
- C++的抽象类继承和构造函数的问题
- 抽象类的复制构造函数中的问题
- 抽象类和虚方法问题:"cannot allocate an object of abstract type"
- 从抽象类继承的抽象方法是否存在任何性能问题
- C++抽象类的问题(我可以用Java做,但不能用C++!)
- 抽象类和继承性的问题
- c++中关于闭包的另一个抽象类问题
- 参考抽象类分配问题
- 为什么我在抽象类中使用结构时遇到问题
- 抽象类和虚方法问题:不能将变量' list '声明为抽象类型' aStack
' aStack - c++,虚拟继承,奇怪的抽象类+克隆问题
- 抽象类的Boost二进制序列化问题