RTB*_*ard 4 c++ function-pointers multiple-inheritance
我今天遇到了一个令人困惑的情况,我希望有人可以向我解释.
我有一个包含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"); }
};
Run Code Online (Sandbox Code Playgroud)
的实例Both在非成员函数,刚刚创建一个新的实例化Both,并返回指针:
Both* createInstanceOfBoth () {
return new Both();
}
Run Code Online (Sandbox Code Playgroud)
最后,有一个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;
};
Run Code Online (Sandbox Code Playgroud)
这就是问题所在.当我调用getEnroll()我的Registry对象并调用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;
}
Run Code Online (Sandbox Code Playgroud)
输出:
Enrolling.
Enrolling.
Run Code Online (Sandbox Code Playgroud)
我注意到,如果我改变的顺序Enroll,并Verify在声明Both类(class Both : public Verify, public Enroll {...}),相反的效果会发生:
Verifying.
Verifying.
Run Code Online (Sandbox Code Playgroud)
我已经确定了一种解决方法,其中使用两个不同命名的函数,而不是使用单个createInstanceOfBoth()函数来创建我Enroll和Verify对象,我使用两个不同命名的函数,具有相同的主体但不同的返回类型:
Enroll* createInstanceOfEnroll () {
return new Both();
}
Verify* createInstanceOfVerify () {
return new Both();
}
Run Code Online (Sandbox Code Playgroud)
然后,在Registry类中,我创建了指向这些函数的函数指针:
Registry () {
enrollGenerator = &createInstanceOfEnroll;
verifyGenerator = &createInstanceOfVerify;
}
Run Code Online (Sandbox Code Playgroud)
当我现在运行程序时,我得到了预期的输出:
Enrolling.
Verifying.
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么第一种方法不起作用?我怀疑它与转换createInstanceOfBoth()为具有不同返回类型的函数指针有关,但我并不完全清楚究竟发生了什么.我现在使用我的解决方法很好,但我很好奇:有没有办法只使用单个createInstanceOfBoth()函数来执行此操作,而不必使用两个相同的函数但具有不同的返回类型?
为了节省将这些放在一个可编辑的示例中的时间和麻烦,我已将此代码发布到https://gist.github.com/833304进行下载.
该函数指针强制转换(将返回的函数Both*视为返回Verify*或Enroll*)是不正确的; 在具有多重继承的情况下,对象内的不同基类不一定从对象的开头开始.函数指针强制转换不执行从派生到基础指针转换Both*为基本指针类型所需的偏移操作.
你可以有一个createInstanceOfBoth功能,但它需要返回Both*; 然后,调用它的代码将使用该结果执行派生到基础的转换.