2013-09-23 15 views
0

我有一系列C++类,我希望它们在功能上都是相同的,但除此之外没有关系。实际上,这些类只会在名称上有所不同。 (这些类将被抛出,并且我不希望某个基类的catch子句吞噬抛出的派生对象。是派生类,但是我希望创建离散的抛出类集合,它们总是被隔离的就像catch块一样。)使用模板准确地克隆类类型?

当然,这个缺点是复制源代码。无论何时需要更改,我都不想更新相同代码的N份副本。

我已经通过#define解决了代码重复问题。但是我认为如果我可以利用模板,它将有助于调试能力。在模板中参数化的唯一东西就是类名称本身。

我尝试以下,这并没有在GCC工作(启用W/C++ 0x中支持):

typedef ClassName<UnrelatedClass1> UnrelatedClass1; 
typedef ClassName<UnrelatedClass2> UnrelatedClass2; 

template<typename ClassName> 
class ClassName 
{ 
    public: 
    ClassName(int foo, float bar) { ... } 
    ~ClassName() { ... } 

    bool SomePublicMethod() { ... } 

    private: 
    ... 
} 

然后,我会用的东西类似于申报实际班

我已经知道上述不起作用;我将它作为我想要完成的概念性示例提供,并且想知道是否有一种方法可以使其工作,除了我正在使用的#define宏方法(它具有减弱的调试能力)之外。 )

回答

3

使用价值专门的模板:

template<int ID> 
class ClassName 
{ 
    public: 
    ClassName(int foo, float bar) { ... } 
    ~ClassName() { ... } 

    bool SomePublicMethod() { ... } 

    private: 
    ... 
} 

typedef ClassName<1> UnrelatedClass1; 
typedef ClassName<2> UnrelatedClass2; 
+1

或者更好的是,使用空类的标签:这种方式,您不必担心关于标签分配或冲突,并可能使用有意义的名称。 'template class ClassName {...}; struct SomeTag {}; typedef ClassName UnrelatedClass1;' –

+1

@IgorTandetnik,更好的是,'typedef ClassName UnrelatedClass1;':) – chris

+0

@chris:是的,我想了一下,当我发送该评论(自删除后) 。 –

0

这听起来不像是一个非常好的主意。

异常类应该捕获特定类型的错误,并使用继承来更一般化错误类型。

因此,例如,你可能有一个“磁盘崩溃例外”,这更普遍的可能是一个“磁盘例外”和更普遍和“IO异常”,并始终处于核心的“的std ::例外”

如果您的所有异常都捕获不同类型/类别的错误,那么为什么它们都具有相同类型的实现。

此外,在模板中混合使用#define的情况并不常见,因为当存在编译器错误时(即使看起来没有引起错误时它看起来更具可读性),它总会使其不易读。

也许你可以提供更多关于你的异常类实现的信息,我可以看看我是否可以进一步帮助你。

+0

1.他们都一样的原因是我重新创建了我自己的专业“std :: exception”。 Mine是我用这个模板克隆的所有异常类的抽象基类。 2.我想创建不混合的例外类别。特别是:RVBAssertion(只会被main捕获)和RVBException(其他所有内容都会从IOException,DeviceException等派生出来,就像您所描述的那样)。 由于... –

+0

...我的摘要类永远不会被捕获(因为它不能被实例化),而RVBAssertion和RVBException是类型兄弟,所以我不必担心RVBException的catch块会吞噬RVBAssertion,反之亦然。 –

+0

一个抽象类只需要一个抽象成员是抽象的(并且不可驯服),它仍然可以在其他成员中提供功能。因此,替换std :: exception可以包含RVBAEx和RVAAs的所有常用代码,但仍然是抽象的。只有接口不能有任何实现,所有的原型必须是纯粹的/抽象的。 – Strings

0

我同意别人说他们应该使用继承。这对于许多目的来说是很棒的(其中之一就是你想要类似课程的原因)。只有当对象相关时,编写派生类并不是强制性的 - 即使只是匹配的功能,它也是很好的,因为你的想法确实是将类似的代码放在一起。

但是,由于您的查询是关于创建多个类,并且我们没有足够的项目视图,我相信您可能确实需要单独的类。一种做法是通过宏。这里有一个例子:

#include <iostream> 
using std::cout; 
using std::endl; 

#define CUSTOM_CLASS(_CL) class _CL\ 
{\ 
     public:\ 
        _CL(int foo, float bar) { cout << "Creating instance with foo=" << foo << ";bar=" << bar << endl;}\ 
     ~_CL() { }\ 
     bool SomePublicMethod() { cout << "Class created\n"; }\ 
}; 

CUSTOM_CLASS(myclass1); 
CUSTOM_CLASS(myclass2); 

int main() 
{ 
    myclass1 instance1(1, 1.3f); 
    myclass2 instance2(2, 0.3f); 
    return 0; 
} 

如果你运行这个使用G ++,你会得到以下结果:

Creating instance with foo=1;bar=1.3 
Creating instance with foo=2;bar=0.3 
+0

请再读一遍我的问题。我*有*继承;我只有一个角落案例,我不想继承,但否则需要相同的代码。 您上面提出的解决方案使用#define,与我自己的解决方案基本相同。我在这里的问题是如果用C++模板可以完成同样的事情。我上面接受的答案给出了多种选择,所有这些都适用于我(但我认为@chris的评论是最好的。) –

+0

'_CL'是一个保留的标识符。另外,这很难看。模板是正确的解决方案,请参阅Iuri Covalisin的答案。 – MSalters