से आधार टेम्पलेट की आभासी विधि को कॉल करना यह अनिवार्य रूप से an earlier question पर अनुवर्ती है (मेरे द्वारा उत्पन्न नहीं है, लेकिन मुझे एक उत्तर में रूचि है)।व्युत्पन्न विविधता टेम्पलेट वर्ग
सवाल यह है:क्यों संकलक/लिंकर व्युत्पन्न वर्ग से आभासी समारोह के लिए कॉल के समाधान में विफल करता है? इस मामले में, व्युत्पन्न वर्ग एक टेम्पलेट वर्ग है जिसमें वैरिएडिक पैरामीटर हैं जो एक ही टेम्पलेट वर्ग के विरुद्ध कई बार एकाधिक विरासत लागू करते हैं (एक बार विविध प्रकार के पैरामीटर में प्रत्येक प्रकार के लिए)।
नीचे ठोस उदाहरण में, व्युत्पन्न वर्ग JobPlant
है, और इसे Worker
से बुलाया जा रहा है। अमूर्त work()
विधि को आमंत्रित करने के लिए workaround()
लिंक और अपेक्षित तरीके से निष्पादित करते समय लिंक करने में विफल रहता है।
/home/g6xLmI/ccpFAanK.o: In function `main':
prog.cpp:(.text.startup+0x8e): undefined reference to `Work<JobA>::work(JobA const&)'
prog.cpp:(.text.startup+0xc9): undefined reference to `Work<JobB>::work(JobB const&)'
prog.cpp:(.text.startup+0xff): undefined reference to `Work<JobC>::work(JobC const&)'
collect2: error: ld returned 1 exit status
Follow this link काम कर वैकल्पिक हल के प्रदर्शन के लिए:
ये लिंक विफलताओं के रूप में ideone द्वारा दिखाए गए हैं।
Job
एक सार आधार वर्ग है, और यह व्युत्पन्न कक्षाओं से जुड़ा हुआ है। Work
एक सार तत्व है जो एक नौकरी करता है।
struct Job { virtual ~Job() {} };
struct JobA : Job {};
struct JobB : Job {};
struct JobC : Job {};
template <typename JOB>
struct Work {
virtual ~Work() {}
virtual void work(const JOB &) = 0;
void workaround(const Job &job) { work(dynamic_cast<const JOB &>(job)); }
};
template <typename PLANT, typename... JOBS> struct Worker;
template <typename PLANT, typename JOB, typename... JOBS>
struct Worker<PLANT, JOB, JOBS...> {
bool operator()(PLANT *p, const Job &job) const {
if (Worker<PLANT, JOB>()(p, job)) return true;
return Worker<PLANT, JOBS...>()(p, job);
}
};
template <typename PLANT, typename JOB>
struct Worker<PLANT, JOB> {
bool operator()(PLANT *p, const Job &job) const {
if (dynamic_cast<const JOB *>(&job)) {
p->Work<JOB>::work(dynamic_cast<const JOB &>(job));
//p->Work<JOB>::workaround(job);
return true;
}
return false;
}
};
एक JobPlant
कि एक Worker
पाता है एक job
प्रदर्शन करने के लिए एक टेम्पलेट वर्ग JOBS
द्वारा parameterized, है: Worker
एक (struct
class
बजाय विशुद्ध रूप से वाक्य रचना अव्यवस्था कम करने) टेम्पलेट कि JOB
को दिखाता है और यह करता है। JOBS
में प्रत्येक नौकरी प्रकार के लिए Work
से विरासत प्राप्त करता है। MyJobPlant
JobPlant
का एक उदाहरण है, और संबंधित Work
सार वर्गों से वर्चुअल work
विधियों को लागू करता है।
template <typename... JOBS>
struct JobPlant : Work<JOBS>... {
typedef Worker<JobPlant, JOBS...> WORKER;
bool worker(const Job &job) { return WORKER()(this, job); }
};
struct MyJobPlant : JobPlant<JobA, JobB, JobC> {
void work(const JobA &) { std::cout << "Job A." << std::endl; }
void work(const JobB &) { std::cout << "Job B." << std::endl; }
void work(const JobC &) { std::cout << "Job C." << std::endl; }
};
int main() {
JobB j;
MyJobPlant().worker(j);
}
हू। वह आसान था। क्या आप समझा सकते हैं कि 'p-> काम क्यों करें (dynamic_cast (नौकरी))' अस्पष्टता त्रुटि देता है? देखें: http://ideone.com/2vL57z –
jxh
@jxh: मेरा संपादन देखें :) – sth
'पी-> कार्य :: कोड()' को निम्नलिखित कोड द्वारा हल करने से समस्या का समाधान भी हो जाता है। कार्य और डब्ल्यू = * पी; w.work (dynamic_cast (नौकरी)); –
JVApen