我的界面声明通常(总是?)遵循相同的方案。这是一个例子:
class Output
{
public:
virtual ~Output() { }
virtual void write( const std::vector<char> &data ) = 0;
protected:
Output() { }
private:
Output( const Output &rhs ); // intentionally not implemented
void operator=( const Output &other ); // intentionally not implemented
};
样板始终是相同的:公共虚拟析构函数,构成实际接口的一些纯虚方法。受保护的默认ctor,禁用的复制构造和复制分配。我开始使用两个小助手宏,可以用来简化上面的
ABSTRACT_BASECLASS_BEGIN(Output)
virtual void write( const std::vector<char> &data ) = 0;
ABSTRACT_BASECLASS_END(Output)
不幸的是,我没有找到一个很好的方法只使用一个宏来做到这一点。更好的是,我想完全避免使用宏。然而,我想到的唯一一件事是代码生成器,这对我来说有点矫枉过正。
在C ++中声明接口的最简单方法是什么 - 直接在语言中。预处理器的使用是可以接受的,但我想避免使用外部代码生成器。
答案 0 :(得分:3)
考虑使用基类:
class NoncopyableBase
{
public:
NoncopyableBase() { }
virtual ~NoncopyableBase() { }
private:
NoncopyableBase(const NoncopyableBase&);
void operator=(const NoncopyableBase&);
};
从此基类派生的任何类都是不可复制的,并且将具有虚拟析构函数。
答案 1 :(得分:3)
就个人而言,我会删除复制构造函数声明。您有纯虚函数,因此无论如何都无法通过切片创建此类的实例。如果派生类由于其拥有的资源的性质而不可复制;它可以标记为不可复制。
然后我将摆脱受保护的默认构造函数;它没有做任何事情,你必须从这个类派生,因为你有纯虚函数,所以它不会阻止任何使用。
虽然标记副本赋值运算符可以防止某人执行*pBase1 = *pBase2
(实际上是无操作),但我个人并不相信尝试阻止它是值得的。由于您的类没有数据成员,因此编译器生成的没有固有的危险,因此用户可以正确使用指针或对基类的引用。
我会选择:
class Output
{
public:
virtual ~Output() {}
virtual void write( const std::vector<char> &data ) = 0;
};
答案 2 :(得分:3)
不幸的是,我没有找到一个很好的方法只用一个宏来做到这一点。
IMO,最简单的解决方案是将默认方法放入宏。像这样:
#include <vector>
#define DEFAULT_CLASS_METHODS(C) public: \
virtual ~C(){}; \
protected: \
C(){}; \
private: \
inline C(const C& rhs){}; \
inline void operator=(const C& other){};
class Output{
DEFAULT_CLASS_METHODS(Output)
public:
virtual void write(const std::vector<char> &data) = 0;
};
这样,* .h文件中每个类定义只需要一个宏。您将需要额外的宏来实际声明一些* .cpp文件中的复制构造函数和赋值运算符,或者您可以使内联的默认复制构造函数和赋值运算符,这将把所有内容都包装到单个宏中。
唯一的问题是你需要输入两次类名。
如果不输入两次类名,有一种不那么优雅的方法:
#include <vector>
#define BEGIN_INTERFACE(C) class C{ \
public: \
virtual ~C(){}; \
protected: \
C(){}; \
private: \
inline C(const C& rhs){}; \
inline void operator=(const C& other){};
BEGIN_INTERFACE(Output)
public:
virtual void write(const std::vector<char> &data) = 0;
};
正如您所看到的,在这种情况下,宏会打开{
括号,这会产生误导。
答案 3 :(得分:2)
这类事情怎么样:
ABSTRACT_BASECLASS(Output,
(virtual void write( const std::vector<char> &data ) = 0;)
(more methods))
(first)(second)(...)
是一个提升预处理器序列,就宏而言,它实际上是单个参数:http://www.boost.org/doc/libs/1_43_0/libs/preprocessor/doc/index.html
#define BASECLASS(name, methods) \
...\
BOOST_PP_SEQ_CAT(methods)\ //will concatenate methods declarations
...\