我试图编写一个程序,其中ServiceWorker的派生类(如消防员)可以“面对”#34;派生类偶然事件(火灾,伤害,抢劫)。对抗会返回一个布尔值,表示它是否成功。例如,面对火灾的消防队员将获得成功,但面对抢劫的消防员则不会。 ServiceWorker将跟踪对抗次数和成功对抗的数量,并采用对抗方法来确定对抗是否成功。
我想使用traits来存储每个派生类ServiceWorker在其类定义中可以面对的内容。但是,在ServiceWorker中,confront方法创建了traits类,但我想在其派生类中对其进行特化,因此每个派生类只知道它可以面对的是什么。
class Incident { };
class Fire : Incident { };
class Robbery : Incident { };
class Injury : Incident { };
class ServiceWorker {
public:
ServiceWorker() : ratio(0), num_success(0), num_confronts(0) {
}
template <typename U>
struct can_confront {
static const bool result = false;
};
double successRatio() {
if(ratio)
return ratio;
else
throw;
}
template <typename T>
void confront(T incident) {
if(can_confront<T>::result)
num_success++;
num_confronts++;
ratio = num_success / num_confronts;
}
protected:
double ratio;
unsigned int num_success;
unsigned int num_confronts;
};
class Firefighter : public ServiceWorker {
public:
template <>
struct can_confront<Fire> {
static const bool result = true;
};
};
修改
所以我设法搞清楚了。我摆脱了模板并且面对虚拟,因此创建一个派生类的ServiceWorker只需要重新定义虚函数并使用ServiceWorker :: confront。我还添加了confront_success()和calc_ratio(),以便更轻松地添加新的ServiceWorkers。我让Firefighter :: confront()接受了FirefighterIncident,它继承自Incident。这样,为Firefighter添加新事件很容易,因为他们只需从FirefigherIncident继承。
class Incident {};
class FirefighterIncident : public Incident {};
class Fire : public FirefighterIncident {};
class RescueCat : public FirefighterIncident {};
class ServiceWorker {
public:
ServiceWorker() : ratio(0), num_success(0), num_confronts(0) {
}
double successRatio() {
if(num_confronts != 0)
return ratio;
else {
std::cout << "Can't divide by zero in ratio!" << std::endl;
throw;
}
}
virtual void confront(const Incident&) {
num_confronts++;
calc_ratio();
}
protected:
double ratio;
unsigned int num_success;
unsigned int num_confronts;
void calc_ratio() {
ratio = num_success / (double) num_confronts;
}
void confront_success() {
num_success++;
num_confronts++;
calc_ratio();
}
};
class Firefighter : public ServiceWorker {
public:
using ServiceWorker::confront;
virtual bool confront(const FirefighterIncident&) { confront_success(); }
};
答案 0 :(得分:0)
在我看来,如果您利用std::true_type
和std::false_type
,事情会变得更加清晰。在基类中,
class ServiceWorker {
public:
template <typename U>
struct can_confront: std::false_type { };
...
并在派生类中
class Firefighter: public ServiceWorker {
public:
template<typename U>
struct can_confront: ServiceWorker::template can_confront<U> { };
...
请注意,我在派生类中重新定义了can_confront
(通过继承),这样我就可以专门化它而不需要专门化ServiceWorker::can_confront
。为此,只需添加
template<>
struct Firefighter::can_confront<Fire>: std::true_type { };
外部类定义。 confront
语句替换为
if
模板方法将起作用
if(can_confront<T>::value)
然而,请记住,即使您通过confront
对象调用它,您仍然会遇到ServiceWorker::can_confront<T>
始终使用Firefighter
的问题。一个简单的解决方法是将confront
的定义复制到每个派生类中。