【问题标题】:Advantages of an empty class in C++C++中空类的优点
【发布时间】:2010-10-27 15:59:01
【问题描述】:

空类可能有哪些优点/用途?

附注: 这个问题对你们中的一些人来说可能听起来微不足道,但它只是用于学习目的,没有实际意义。仅供参考,谷歌搜索没有帮助。

【问题讨论】:

  • 在几种情况下这很有用;你能举个例子,让我们有一些背景吗?
  • 空,因为没有成员或函数;还是像使用 Null Object 模式一样为空?
  • 你看到这个链接cplusplus.com/forum/general/8370了吗?
  • 空,因为没有成员或函数。
  • @Ron,你的意思是真的空类吗,比如空类{}; ?好吧,我从来没有机会使用它。

标签: c++ class


【解决方案1】:

一种用途是在模板(元)编程中:例如,iterator tags 被实现为空类。这里的唯一目的是在编译时传递信息,以便您检查迭代器是否传递给例如模板函数满足特定要求。

示例:

这是真正简化的,只是为了提出一个想法。这里标记类的目的是决定使用哪种算法实现:

class forward_iterator_tag {};
class random_access_iterator_tag {};

class MySimpleForwardIterator {
public:
  typedef typename forward_iterator_tag tag;
  // ...
};

class MySimpleRandomIterator {
public:
  typedef typename random_access_iterator_tag tag;
  // ...
};

template<class iterator, class tag>
void myfunc_int(iterator it, tag t) {
  // general implementation of myfunc
}

template<class iterator>
void myfunc_int<iterator, forward_iterator_tag>(iterator it) {
  // Implementation for forward iterators
}

template<class iterator>
void myfunc_int<iterator, random_access_iterator_tag>(iterator it) {
  // Implementation for random access iterators
}

template<class iterator>
void myfunc(iterator it) {
  myfunc_int<iterator, typename iterator::tag>(it);
}

(我希望我做对了,我已经有一段时间没有使用它了......)

使用此代码,您可以在任意迭代器上调用myfunc,并让编译器根据迭代器类型(即标记)选择正确的实现。

【讨论】:

  • 看一些STL迭代器的实现,任何编译器都应该有代码
  • 成语叫tag dispatching
【解决方案2】:

以下可用于拥有一个boost::variant,它可以保存一个(SQL)NULL值。

class Null { };

typedef boost::variant<Null, std::string, int> Value;

为了让它更有用,operator==operator&lt;&lt; 这样的东西很方便。例如:

std::ostream& operator<<(std::ostream &lhs, const Null &rhs)
{
     lhs << "*NULL*";
     return lhs;
}

int main()
{
    Variant v("hello");
    std::cout << v << std::endl;
    v = Null();
    std::cout << v << std::endl;
    ...
}

将给予:

hello
*NULL*

【讨论】:

    【解决方案3】:

    在 STL,C++ 的标准模板库中,例如你有

    template<class _Arg,
     class _Result>
    struct unary_function
        { // base class for unary functions
     typedef _Arg argument_type;
     typedef _Result result_type;
        };
    

    在定义函子时,您可以继承 unary_function,然后您可以使用自动定义的 typedef。

    【讨论】:

      【解决方案4】:

      空类可以用作定义独特事物的“令牌”;在某些模式中,您需要一个唯一实例的与实现无关的表示,除了其唯一性之外,它对开发人员没有任何价值。一个例子是工作单元;你可能一点也不关心你的执行者内部发生了什么,但你想告诉那个执行者你告诉它执行的任务是原子集的一部分。在这种情况下,一个向外界表示工作单元的空类可能是完美的;几乎工作单元对象可以存储或执行的任何操作(封装数据库事务、公开提交/回滚行为)都会开始将您绑定到特定的实现,但是对象引用对于提供对原子的唯一但可复制和可传递的引用很有用一组任务。

      【讨论】:

        【解决方案5】:

        您可以将其用作检查目的的占位符或用作特殊功能的启用程序。例如,在 Java 中存在用于指定类是否可序列化的“空”接口 Serializable。

        【讨论】:

          【解决方案6】:

          “空”类是指没有数据成员的类? 它们通常声明 typedef 或成员函数,您可以使用自己的类对其进行扩展。

          【讨论】:

          • (英语不是我的母语)伪代码类 Shape { virtual double area(); } 类圆形扩展形状 { 双区域() } 类方形扩展形状 { 双区域() }
          • 您可以通过选择“编辑”按钮来编辑您的答案并将代码示例放在那里而不是在 cmets 中。这使它更具可读性。
          【解决方案7】:

          Here 是一个有趣的链接,其中包含为什么允许它的答案。您可能会发现这有助于找到可能有用的情况。

          【讨论】:

          • 你提到的那篇文章没有提到任何 data 成员。只有函数成员的类被广泛使用(例如用于接口定义)。我认为 OP 意味着没有 any 成员的空类。
          • @MartinStettner - 我在这个问题中的帖子提到了为什么它被允许。我发布的另一篇文章是展示 Javi 的答案来自哪里。阅读文章,您会在文章中逐字看到答案。我没有将其发布为答案。
          【解决方案8】:

          正如其他人所说,空类(或结构)通常用作占位符、区分符、标记等。

          例如,很多人不知道 operator new 有“nothrow”版本。调用 nothrow new 的语法是:

          p = new(std::nothrow) Bar;
          

          而 std::nothrow 被简单地定义为

          struct nothrow_t {}; //defined in namespace std
          

          【讨论】:

            【解决方案9】:

            MartinStettner 的回答很好,但只是为了强调一个重点:迭代器标签的概念或 C++ 中的任何标签,并不严格依赖于空类。如果 stl 编写者想要的话,C++ 标签很可能是非空类;这应该可以工作,但不会增加任何额外的价值;至少对于它通常保留的编译时杂技。

            【讨论】:

              【解决方案10】:

              为了typeid

              假设我们有类似的接口Id。我们需要用这个接口的唯一实例填充一些容器。如何保证独立软件部分产生的Id实例的唯一性? «独立部分»是指一些不同的动态库,由不同的程序员在不同的地方编译

              其中一个决定是首先比较某种类型的typeid。如果typeid 匹配,则转换并比较其他实现特定的属性。 C++ 语言保证进程内存中任何类型的唯一性。为此应使用哪种类型?任何资源消耗最少的类型——空一个

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2010-11-22
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-03-03
                相关资源
                最近更新 更多