今天我遇到了一个令人困惑的情况,希望有人能够解释一下。
我有一个包含4个类的C++程序:
- 一个
Base
类,只作为一个公共接口, - 一个
Enroll
类,它是Base
的子类,并具有一个纯虚拟的enroll()
方法, - 一个
Verify
类,也是Base
的子类,并具有一个纯虚拟的verify()
方法, - 一个
Both
类,它同时是Enroll
和Verify
的子类,并提供了enroll()
和verify()
的实现。
如下所示:
class Base {
public:
Base () { }
virtual ~Base () { }
};
class Enroll : public virtual Base {
public:
virtual ~Enroll () { }
virtual void enroll () = 0;
};
class Verify : public virtual Base {
public:
virtual ~Verify () { }
virtual void verify () = 0;
};
class Both : public Enroll, public Verify {
public:
virtual ~Both () { }
virtual void enroll () { printf ("Enrolling.\n"); }
virtual void verify () { printf ("Verifying.\n"); }
};
Both
的实例是在一个非成员函数中实例化的,它只创建一个新的Both
并返回指针:
Both* createInstanceOfBoth () {
return new Both();
}
最后,有一个Registry
类,基本上只是作为Enroll
/Verify
工厂的作用。它使用一对函数指针来调用createInstanceOfBoth()
函数,以提供Enroll
或Verify
的实例:
typedef Enroll* (*EnrollGenerator) ();
typedef Verify* (*VerifyGenerator) ();
class Registry {
public:
Registry () {
enrollGenerator = (EnrollGenerator)&createInstanceOfBoth;
verifyGenerator = (VerifyGenerator)&createInstanceOfBoth;
}
Enroll* getEnroll () { return enrollGenerator (); }
Verify* getVerify () { return verifyGenerator (); }
EnrollGenerator enrollGenerator;
VerifyGenerator verifyGenerator;
};
以下是翻译的结果:
这里出现了问题。当我在Registry
对象上调用getEnroll()
并在返回的对象上调用enroll()
时,我看到了正确的预期输出:Enrolling.
但是,当我调用getVerify()
并在返回的对象上调用verify()
时,enroll()
方法会再次执行!
代码:
int main () {
Registry registry;
Enroll *enroller;
Verify *verifier;
enroller = registry.getEnroll ();
verifier = registry.getVerify ();
enroller->enroll ();
verifier->verify ();
return 0;
}
输出:
Enrolling.
Enrolling.
我注意到,如果我在声明Both
类时改变Enroll
和Verify
的顺序(class Both : public Verify, public Enroll {...}
),相反的效果将会发生:
Verifying.
Verifying.
我发现一个解决方法,不再使用单一的createInstanceOfBoth()
函数创建我的Enroll
和Verify
对象,而是使用两个不同命名的函数,它们具有相同的主体但是返回类型不同:
Enroll* createInstanceOfEnroll () {
return new Both();
}
Verify* createInstanceOfVerify () {
return new Both();
}
然后,在Registry类中,我创建指向这些函数的函数指针:
Registry () {
enrollGenerator = &createInstanceOfEnroll;
verifyGenerator = &createInstanceOfVerify;
}
当我现在运行程序时,我得到了预期的输出:
Enrolling.
Verifying.
我的问题是:为什么第一种方法不起作用?我怀疑这与将
createInstanceOfBoth()
转换为具有不同返回类型的函数指针有关,但我不完全理解正在发生的事情。目前使用我的解决方法没问题,但我很好奇:是否有一种方法可以只使用单个createInstanceOfBoth()
函数而不必使用两个具有不同返回类型但相同的函数来完成此操作?为了节省时间和麻烦,我已将此代码发布到https://gist.github.com/833304以供下载。
Base
子类的方法时,我偶然遇到了这种情况,尽管生产代码不会涉及任何类似于这个例子的东西,但它仍然让我感到困惑,直到我理解了发生了什么才能放下并继续前进。 - RTBarnard