【问题标题】:The difference between #include .h and just stating class A; in C++ [duplicate]#include .h 与仅声明 A 类之间的区别;在 C++ [重复]
【发布时间】:2013-08-28 19:52:16
【问题描述】:

我正在为学校分析一个操作系统项目,并遇到了这个头文件:

//kernelev.h

#ifndef _KERNELEV_H 
#define _EVENT_H_

typedef unsigned char IVTNo;

class Thread;
class PCB;
class KernelSem;

class KernelEv {
public:
     KernelEv (IVTNo ivtNo);
     ~KernelEv();
     int wait(int MaxTimeToWait);
     void signal();

[...]

现在,在编写这些方法(KernelEv、~KernelEv、wait 和 signal)的完整定义时,他们使用了 Thread、PCB 和 KernelSem 类的属性。通常引入例如#include Thread.h有什么区别; #include KernelSem.h;并且只声明这样的类:class Thread;数据访问权限是否存在差异?还是完全不同?

感谢您的帮助,希望我的问题足够清楚。

【问题讨论】:

  • 对我来说听起来不太一样
  • @Dave 听起来不太一样,但答案足以回答这个问题。
  • 小心你的包含警卫!您使用的是reserved names,更关键的是,这两个名称不匹配。
  • 实际上,前向声明主题对我有用。谢谢你,juanchopanza!
  • 使用前向声明的要点(手动打破循环依赖,因为 C++ 解析器本质上是一个单通道解析器)仅在小注释中提及。

标签: c++ class header


【解决方案1】:

首先请注意,如果只引入类,将无法使用方法;

class Thread;

Thread x; // compile error: size of x unknown
Thread* x; // this is ok
// set x to some valid thread, maybe as a parameter
x->signal(); // compile error

但是,无论您的声明是在标题中还是包含在文件中,都没有区别。也就是说,您可以将include 行替换为标题的副本,并且一切都可以正常工作(上面示例中的每一行都是有效的)。然而,有很多理由不这样做。易于维护以及可读性和模块化将是首要问题。它也不太适用于编译器缓存(因此通常需要更长的时间来编译)

【讨论】:

    【解决方案2】:

    如果您只有一个声明class A; 而不是完整的类定义,那么该类型被称为不完整。这可以以有限的方式使用;你可以做一些只需要知道类存在的事情,例如:

    • 声明一个指针或对它的引用;
    • 声明一个函数,将其用作参数或返回类型;
    • 声明(但不定义)该类型的外部变量。

    你不能做任何需要知道类成员、大小或定义给出的其他细节的事情,例如:

    • 定义该类型的变量;
    • 使用它定义一个函数;
    • 访问任何成员或嵌套声明;
    • 从它继承;
    • 申请sizeof。

    【讨论】:

      【解决方案3】:

      如果我没记错的话,你问的是Declaration vs Definition。它们不同但相关。

      我将您转发到这两个用谷歌搜索为“c++ 声明定义”的帖子,因为它们会比我解释得更好:)

      What is the difference between a definition and a declaration?

      http://www.cprogramming.com/declare_vs_define.html

      只需评论您的class A; 是declaration,而包含Thread.h 肯定会有很多definitions 内部(可能还有声明)。

      ---------编辑:

      关于@Dave 评论的前向声明:

      class B ; // needed declaration
      
      class A {
        B field ;
      } ;
      
      class B {
        A field ;
      };
      

      【讨论】:

      • 哦,不。我(想我)知道这两者之间的区别。我只是想知道我使用“不完整的类声明”类 Thread 的动机是什么; PCB类;等等,而不是包含相应的头文件(确实存在):#include "Thread.h" #include "PCB.h" ... 等等。有什么区别,我为什么要这样做?有什么想法吗?
      • @StefanWœlfisch 如果您需要两个类来相互了解,或者如果您的程序模块只处理指向某些类的指针(在这种情况下为它们提供完整的类)定义只是为了延长编译时间)
      • 如果你不定义线程的内部,编译器将一无所知。那么,为什么会有那个声明呢? :S(自引用或循环在哪里?)
      • 好吧,如果标头不使用那些方法,它就不需要知道它们。实现(在包含目录中不可用)将知道完整的定义。通过仅使用声明,标头可以更快地编译。或者如果它稍后定义它们,它正在做我提到的第一点(类相互了解)
      • @Dave: 没什么可反对的 :)
      猜你喜欢
      • 2016-04-20
      • 2017-10-05
      • 2015-07-29
      • 2011-02-20
      • 2014-11-21
      • 2011-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多