C++父类调用子虚拟功能
问题描述:
我想要一个纯虚父类调用,像这样一个孩子实现一个功能:C++父类调用子虚拟功能
class parent
{
public:
void Read() { //read stuff }
virtual void Process() = 0;
parent()
{
Read();
Process();
}
}
class child : public parent
{
public:
virtual void Process() { //process stuff }
child() : parent() { }
}
int main()
{
child c;
}
这应该工作,但我得到一个未链接错误:/这是使用VC++ 2k3
或者它不应该工作,我错了吗?
答
一般会工作,但不适用于纯虚拟基类的构造函数中的调用。在构建基类时,子类覆盖不存在,因此您不能调用它。只要您在构建完整个对象后调用它,它就可以工作。
答
这是因为你的调用是在构造函数中。在构造函数完成之前,派生类将无效,因此您的编译器正在为此定下决心。
有两个解决方案:
- 执行调用以处理()在子类的构造函数
- 定义毛坯功能体用于过程如下面的例子:
class parent
{
public:
void Read() { //read stuff }
virtual void Process() { }
parent()
{
Read();
Process();
}
}
答
或者,建立一个工厂方法来创建对象并使构造函数为私有,工厂方法可以在构造之后初始化该对象。
答
你需要用在调用虚拟方法的对象中后,对象完全构造:
class parent
{
public:
void Read() { /*read stuff*/ }
virtual void Process() = 0;
parent()
{
Read();
}
};
class child: public parent
{
public:
virtual void Process() { /*process stuff*/ }
child() : parent() { }
};
template<typename T>
class Processor
{
public:
Processor()
:processorObj() // Pass on any args here
{
processorObj.Process();
}
private:
T processorObj;
};
int main()
{
Processor<child> c;
}
答
足下越多,你可能只是引入某种功能像
class parent
{
public:
void initialize() {
read();
process();
}
}
答
肤浅问题是你调用一个还不知道的虚拟函数(对象是由Parent to Child构造的,因此vtable也是如此)。你的编译器警告过你。
必不可少的问题,据我所知,是你试图通过继承重用功能。这几乎总是一个坏主意。设计问题,可以这么说:)
本质上讲,你尝试实例化一个模板方法模式,从而分离出什么从当:先读一些数据(以某种方式),然后处理它(在某种方式)。
这可能会更好地处理聚合:将Processing函数赋予Template方法以在正确的时间调用。也许你甚至可以为Read功能做同样的事情。
聚集可以通过两种方式来完成:
- 使用虚拟功能(即运行时绑定)
- 使用模板(即编译时间绑定)
实施例1:运行时绑定
class Data {};
class IReader { public: virtual Data read() = 0; };
class IProcessor { public: virtual void process(Data& d) = 0; };
class ReadNProcess {
public:
ReadNProcess(IReader& reader, IProcessor processor){
processor.process(reader.read());
}
};
实施例2:编译时结合
template< typename Reader, typename Writer > // definitely could use concepts here :)
class ReadNProcess {
public:
ReadNProcess(Reader& r, Processor& p) {
p.process(r.read());
}
};
这是危险的,定义一个空白父函数体并在其构造函数中调用它将导致只执行Process()的父部分(即无)。他可能希望将该调用作为虚函数解析,这在构造函数中是不可能的 – Pieter 2008-10-24 08:25:51
确实:将调用空函数。这不是可行的解决方案。 – xtofl 2008-10-24 09:32:49