2011-06-04 53 views
4

想象一下这个简单的基类:强制派生类重写至少一个虚函数

struct simple_http_service 
{ 
    virtual reply http_get(…); 
    virtual reply http_post(…); 
    virtual reply http_delete(…); 
    // etc. 
}; 

我想防止用户从此类派生没有覆盖的至少其中之一,并防止他们instantiang simple_http_service

是否有一些不错方式做到这一点?

+0

我90%肯定没有这样做的一个非常好的方法,尤其是很难表达的约束类似于C++ – 2011-06-04 09:33:11

+2

呃做这些中的一个,似乎是靠不住的设计。如果他们忽略了三种功能中的两种功能,还有什么? – GManNickG 2011-06-04 09:37:09

+2

如果您提供了所有这些功能的良好默认实现,那么如果有人想要派生出一个全部使用它们的类,那么为什么它对您很重要? – 2011-06-04 09:40:06

回答

5

这听起来像一个非常奇怪的约束。通过一切手段保护用户免受不正确使用,但不要试图禁止的东西,你只是“看不到的地步”。如果有,从你的类派生没有覆盖所有的三个功能是没有意义的,然后让他喜欢的用户覆盖尽可能多或尽可能少的功能,并相信他不会做得出的,无关紧要的事情,而不覆盖任何的功能。用户这样做并没有什么坏处,但它不是很有用。

但是,如果你需要强制执行(再次,我建议你重新考虑),那么不要使用虚拟功能。而是传递函数指针或函数对象(或std::function/boost::function)回调函数。让基类是这个样子:

struct simple_http_service 
{ 
    typedef std::function<reply (...)> func_type; 
    reply http_get(...) { return get_func(...); } 
    reply http_post(...) { return post_func(...); } 
    reply http_delete(...) { return delete_func(...); } 
    // etc. 

private: 
    func_type get_func; 
    func_type post_func; 
    func_type delete_func; 
}; 

现在只需添加必要的构造函数(或免费/静态功能,所以你可以为它们命名,以避免歧义),这样的类只能当至少一个实例提供函数对象。

+0

我必须承认你是对的:) – 2011-06-04 10:14:10

+4

+1这是一个非常好的方法,很多人在第一遍中都没有把握。我使用它,我推荐它。对于偶然的读者来说:这意味着你不会*实现*不同的服务,而是*单一的服务,并且在构建过程中你可以将它设置为派发到操作的句柄。您可以提供不同的* service *实例,它们将通过使用'std :: bind'来控制调度,或者可以将调度到单独的* service *中的不同类,派发到基础模型中相同类中的不同操作方法比继承更灵活 – 2011-06-04 10:17:38

0

如果知道你想要的派生类覆盖的方法,只需声明方法pure virtual

例如,使HTTP_GET纯虚:

struct simple_http_service 
{ 
    virtual reply http_get(…) = 0; 
    virtual reply http_post(…); 
    virtual reply http_delete(…); 
    // etc. 
}; 
+0

这正是我的问题 - 我不知道哪个会被重写,但我想强制重写至少一个。 – 2011-06-04 09:37:37

+0

@Karl:“但我想强制重写至少一个”为什么? – GManNickG 2011-06-04 09:38:39

+0

@GMan因为我不希望它有可能实例化基类。我想我会编辑这个问题... – 2011-06-04 09:40:41

1

我认为所有的这些功能应该是纯虚函数。你发布的结构实际上是一个接口。如果函数并非都是必需的,派生的结构只应该为与它们无关的函数提供一个空的实现。

1

如果你只是想执行的基类是抽象的,给它一个纯虚析构函数,使您的多种功能的普通虚拟的。