首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么在.h文件中使用#ifndef CLASS_H和#define CLASS_H而在.cpp中没有?

在C++编程中,头文件(.h文件)和源文件(.cpp文件)分别扮演着不同的角色。头文件主要用于声明类、函数和变量等,而源文件则包含了具体的实现代码。为了避免头文件被重复引用,导致类、函数和变量的重复定义,我们需要在头文件中使用预处理指令来防止这种情况的发生。

在头文件中,我们使用#ifndef#define来实现这个目的。#ifndef用于检查括号内的宏是否未定义,如果未定义,则执行后面的代码。#define用于定义一个宏,这里我们定义一个名为CLASS_H的宏。这样,当头文件被多次引用时,CLASS_H宏已经被定义,#ifndef条件不再满足,后面的代码就不会被执行,从而避免了重复定义的问题。

在源文件中,我们通常不使用#ifndef#define这样的预处理指令,因为源文件中的代码通常只被编译一次。如果在源文件中也使用这些指令,可能会导致编译错误或者程序行为的异常。

总结一下,我们在头文件中使用#ifndef#define来防止重复定义,而在源文件中则不需要这些指令,因为源文件中的代码只会被编译一次。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

  • C++防止头文件被重复引入的3种方法!

    之前我们详细介绍了 C 语言中如何使用宏定义(#ifndef / #define / #endif)来有效避免头文件被重复 #include,此方式 C++ 多文件编程也很常用。...这是因为 school.h 文件已经 #include 了一次 "student.h",而在 main.cpp 主程序又同时 #include 了 "school.h" "student.h",...有小伙伴可能想到,既然 School.h 文件已经引入了 Student 类,那去掉 main.cpp 主程序引入的 student.h 文件不就可以了吗?...———————— 1) 使用宏定义避免重复引入 实际多文件开发,我们往往使用如下的宏定义来避免发生重复引入: #ifndef _NAME_H #define _NAME_H //头文件内容 #endif...另外在某些场景,考虑到编译效率可移植性,#pragma once #ifndef 经常被结合使用来避免头文件被重复引入。

    5.2K40

    【头文件】对.h文件的理解

    为了解决这个问题,人们将重复的部分提取出来放在一个新文件,即“头文件”,通常使用.h扩展名。这些头文件包含了变量函数的全局性声明,被其他.c文件共享,方便修改维护大型代码。....h文件实现函数不会出错的原因是因为.h文件的内容预处理阶段被直接包含到调用它的源文件而在编译阶段,编译器只关注源文件的内容,而不关心它是如何被包含的。...简单示例 2.1 头文件addition.h addition.h内容如下: #ifndef ADDITION_H #define ADDITION_H // 函数声明 int add(int a,...int b); #endif /* ADDITION_H */ 补充: 头文件为什么喜欢写类似下面的内容: #ifndef ADDITION_H #define ADDITION_H //内容。...#ifndef ADDITION_H: 这是一个预处理器指令,意为 "if not defined",即如果宏 ADDITION_H 没有被定义过,则执行下面的代码。

    25410

    【编程基础】extern C的用法解析

    未加extern "C"声明时的连接方式 假设在C++,模块A的头文件如下: // 模块A头文件 moduleA.h #ifndef MODULE_A_H #define MODULE_A_H int...加extern "C"声明后的编译连接方式 加extern "C"声明后,模块A的头文件变为: // 模块A头文件 moduleA.h #ifndef MODULE_A_H #define MODULE_A_H..." }   而在C语言的头文件,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,.c文件包含了extern "C"时会出现编译语法错误。   ...笔者编写的C++引用C函数例子工程包含的三个文件的源代码如下: /* c语言头文件:cExample.h */ #ifndef C_EXAMPLE_H #define C_EXAMPLE_H extern...笔者编写的C引用C++函数例子工程包含的三个文件的源代码如下: //C++头文件 cppExample.h #ifndef CPP_EXAMPLE_H #define CPP_EXAMPLE_H extern

    98930

    C++调用C链接库会出现的问题

    以下是假设旧的C程序库 C的头文件 /*-----------c.h--------------*/ #ifndef _C_H_ #define _C_H_ extern int add(int x,...编译cpp.cpp编译器cpp文件中发现add(1, 0);的调用而函数声明为extern int add(int x, int y);编译器就决定去找[email=add@@YAHHH@Z]add...,想要利用以前的C程序库,那么你就要学会它,我们可以看以下标准头文件你会发现,很多头文件都有以下的结构 #ifndef __H #define __H #ifdef __cplusplus extern.../ 如果我们仿制该头文件可以得到 #ifndef _C_H_ #define _C_H_ #ifdef __cplusplus extern "C" { #endif extern int add(int...extern "C" {},windows是采用C语言编制他首先要考虑到C可以正确调用这些DLL,而用户可能会使用C++而extern "C" {}就会发生作用 当原来的C语言写的头文件里面没有考虑这个问题的时候

    1.1K30

    为什么C语言会有头文件

    前段时间一个刚转到C语言的同事问我,为什么C会多一个头文件,而不是像JavaPython那样所有的代码都在源文件。...因为编译add.cpp时生成的add.obj中有函数add的定义,而在main文件又有add函数的定义。...,我们来试试引入两个, 在这个项目中新增一个mul文件来编写一个乘法的函数 #define __ADD_H__ #include "add.cpp" int mul(int x, int y); #ifndef...最后main引用这个函数 #define __ADD_H__ #define __MUL_H__ #include "add.cpp" #include "mul.cpp" int main()...C语言编译过程 在上面我基本上回答了为什么需要一个头文件,但是本质的问题还是没有解决,为什么像Python这类动态语言也有对应模块、多文件,但是它不需要像C那样要先声明才能使用

    2.2K50

    关于opentelemetry-cpp社区对于C++ Head Only组件单例符号可见性的讨论小记

    前言 前段时间有人在 opentelemetry-cpp 提出了api组件动态库单例无法工作的 issue ,( https://github.com/open-telemetry/opentelemetry-cpp...这种情况又不太一样,各个模块会直接使用本地的函数,不再从GOT查找。导致各个模块最终使用的同名变量函数地址不一样。...而在PE,dll调用函数,除非标记为 __declspec(dllimport),总是从本模块的符号表总查找。...所以这个申明必须位于 cpp 文件,不能位于头文件。这就和前面提到的 opentelemetry-cpp 规范要求 api组件必须是header-only的 相冲突。而但凡写在头文件里。... opentelemetry-cpp 还通过 inline namespace 机制来隔离多版本的ABI兼容性(仅限于stable接口)。

    1.1K30

    c++两个类互相引用的问题

    我会搭建一个简单的程序来模拟这个错误,因为程序是在有些多~ 警告的来源:       一个头文件A.h包含class A的代码如下:   #ifndef AH #define AH class B;...A.h的代码: #ifndef AH #define AH class B; class A { B b; }; #endif    B.h的代码: #ifndef BH #define BH #include...“warning C4150: 删除指向不完整“B”类型的指针;没有调用析构函数”       而且另外的一个问题是该.h文件不能使用该指针调用这个类的成员,原因也是定义不可见。                ...“error C2227: “->haha”的左边必须指向类/结构/联合/泛型类型” 解决方案:       此时需要将A.h的所有成员函数实现重新定义一个.cpp文件,然后该.cpp文件去#include...A.h #ifndef AH #define AH class B; class A { public: B* b; void setB(); ~A(); }; #endif     B.h #ifndef

    1.3K20

    c++两个类互相引用的问题

    我会搭建一个简单的程序来模拟这个错误,因为程序是在有些多~ 警告的来源:       一个头文件A.h包含class A的代码如下:   #ifndef AH #define AH class B;...A.h的代码: #ifndef AH #define AH class B; class A { B b; }; #endif    B.h的代码: #ifndef BH #define BH #include...“warning C4150: 删除指向不完整“B”类型的指针;没有调用析构函数”       而且另外的一个问题是该.h文件不能使用该指针调用这个类的成员,原因也是定义不可见。                ...“error C2227: “->haha”的左边必须指向类/结构/联合/泛型类型” 解决方案:       此时需要将A.h的所有成员函数实现重新定义一个.cpp文件,然后该.cpp文件去#include...A.h #ifndef AH #define AH class B; class A { public: B* b; void setB(); ~A(); }; #endif     B.h #ifndef

    1.2K20

    c++两个类互相引用的问题

    我会搭建一个简单的程序来模拟这个错误,因为程序是在有些多~ 警告的来源:       一个头文件A.h包含class A的代码如下:   #ifndef AH #define AH class B;...A.h的代码: #ifndef AH #define AH class B; class A { B b; }; #endif    B.h的代码: #ifndef BH #define BH #include...“warning C4150: 删除指向不完整“B”类型的指针;没有调用析构函数”       而且另外的一个问题是该.h文件不能使用该指针调用这个类的成员,原因也是定义不可见。                ...“error C2227: “->haha”的左边必须指向类/结构/联合/泛型类型” 解决方案:       此时需要将A.h的所有成员函数实现重新定义一个.cpp文件,然后该.cpp文件去#include...A.h #ifndef AH #define AH class B; class A { public: B* b; void setB(); ~A(); }; #endif     B.h #ifndef

    1.9K50

    c++DLL编程详解

    LIB: VC++6.0新建一个名称为libTest的static library工程,并新建lib.hlib.cpp两个文件,lib.hlib.cpp的源代码如下: //文件:lib.h #ifndef...在建立的工程添加MyDll.h及MyDll.cpp文件,源代码如下: /* 文件名:MyDll.h */ #ifndef MYDLL_H #define MYDLL_H extern "C" int...从MyDll.hMyDll.cpp可以看出,全局变量DLL的定义使用方法与一般的程序设计是一样的。...下面的例子里,DLL定义了pointcircle两个类,并在应用工程引用了它们//文件名:point.h,point类的声明 #ifndef POINT_H #define POINT_H #ifdef..._declspec(dllexport) circle //导出类circle { … } 而在应用工程没有定义DLL_FILE,故其包含point.hcircle.h后引入的类声明为: class

    2.3K60

    适合具备 C 语言基础的 C++ 入门教程(九)

    Chinese Englishman,那么实例化对象的时候,我们实际上是不会用到Human类去定义一个对象的,考虑到这层因素,我们 Human类里使用到了纯虚函数的概念,类实现的代码如下所示:...多文件编程 在前面的教程,有一则教程说到了多文件编程, C++也就是将类的声明放到头文件,将类的实现放在.cpp文件,为了更好地阐述这种方法,我们用实例来进行讲解,首先,来看一下,所涉及到地所有文件有哪些...: [image-20210222103409774] 可以看到上述有6个文件,我们首先来看 Chinese.h这个文件,代码如下所示: #ifndef _CHINESE_H #define _CHINESE_H...,首先是Englishman.h的代码,代码如下所示: #ifndef _ENGLISHMAN_H #define _ENGLISHMAN_H #include #include...Englishman都有名字,那么就可以增添设置名字获取名字这两种方法,首先是 Chinese的代码,代码如下: #ifndef _CHINESE_H #define _CHINESE_H #include

    41610

    适合具备 C 语言基础的 C++ 教程(九)

    Chinese Englishman,那么实例化对象的时候,我们实际上是不会用到Human类去定义一个对象的,考虑到这层因素,我们 Human类里使用到了纯虚函数的概念,类实现的代码如下所示:...多文件编程 在前面的教程,有一则教程说到了多文件编程, C++也就是将类的声明放到头文件,将类的实现放在.cpp文件,为了更好地阐述这种方法,我们用实例来进行讲解,首先,来看一下,所涉及到地所有文件有哪些...image-20210222103409774 可以看到上述有6个文件,我们首先来看 Chinese.h这个文件,代码如下所示: #ifndef _CHINESE_H #define _CHINESE_H...,首先是Englishman.h的代码,代码如下所示: #ifndef _ENGLISHMAN_H #define _ENGLISHMAN_H #include #include...Englishman.h的代码: #ifndef _ENGLISHMAN_H #define _ENGLISHMAN_H #include #include <string.h

    40220

    C++如何调用写好的C接口?

    ,a,b); } 一个头文件test.h #ifndef _TEST_H #define _TEST_H void print(int a,int b); #endif C++文件调用C函数 #...原因分析 test.c我们使用的是C语言的编译器gcc进行编译的,其中的函数print编译之后,符号表的名字为 print,通过nm查看.o文件. $ gcc -c test.c $ nm test.o...printf 0000000000000000 T _Z5printii 此时如果我们在对print的声明中加入 extern “C” ,这个时候,g++编译器就会按照C语言的链接方式进行寻找,也就是符号表寻找...总结 编译后底层解析的符号不同,C语言是 _print,C++是 __Z5printii 解决调用失败问题 修改test.h文件 #ifndef _TEST_H #define _TEST_H extern...extern “C“这种写法 C接口既能被C++调用又能被C调用 为了使得test.c代码既能被C++调用又能被C调用 将test.h修改如下 #ifndef __TEST_H__ #define __

    1.2K10

    #ifndef#define#endif使用详解

    想必很多人都看过“头文件的 #ifndef/#define/#endif 防止该头文件被重复引用”。但是是否能理解“被重复引用”是什么意思?...是不能在不同的两个文件使用include来包含这个头文件吗?如果头文件被重复引用了,会产生什么后果?是不是所有的头文件中都要加入#ifndef/#define/#endif 这些代码?...其实“被重复引用”是指一个头文件同一个cpp文件中被include了多次,这种错误常常是由于include嵌套造成的。...比如:存在a.h文件#include "c.h"而此时b.cpp文件导入了#include "a.h" #include "c.h"此时就会造成c.h重复引用。...下面给一个#ifndef/#define/#endif的格式: #ifndef A_H意思是"if not define a.h" 如果不存在a.h 接着的语句应该#define A_H 就引入

    1.1K30

    CCPP分文件编写

    从这里我们可以看出:我们将函数定义放在一个文件调用函数之前只需要声明一下就可以了。这里没有将函数声明写在头文件,而是直接在用之前就临时声明一下。...那么真正的项目开发过程,我们为什么不直接在调用之前直接声明一下而是将函数声明写入头文件呢?我们这么做就是为了编写代码方便,写入头文件中就不用重复的各个.c/.cpp文件中去写函数声明。...那么还有一个问题啊,就是我们知道,函数变量的定义只能有一次,但是函数的声明可以有多次。如果我main.cpp多次包含了同一个头文件会怎么样呢?...> // 所有头文件的包含都需要在#pragma once语句之后 extern int myStrlen(char* myStr); 2.文件写上: #ifndef _MYSTRLEN_H...// _MYSTRLEN_H是根据头文件名来写的 都是大写字母 #define _MYSTRLEN_H #endif 因此我们也可以使用这种方法来修改myStrlen.h(Qt中都是使用这种方式的):

    54820

    【C++】类的声明 与 类的实现 分开 ① ( 类的声明 与 类的实现 常用用法 | Visual Studio 2019 创建类的头文件文件 | 确保头文件包含一次 )

    , 类的声明 与 类的实现 是分开的 , 这样可以使程序代码更清晰 , 易于管理 维护 ; .h 后缀 的头文件 写 类的声明 代码 ; .cpp 后缀 的源码文件 写 类的实现 代码...; 上述 .h 后缀 的头文件 .cpp 后缀 的源码文件 , 可以手动创建添加 , 也可以使用 IDE 自带的创建类功能添加 , 这里推荐后者 , 下面的章节讲解 Visual Studio...选项 , 弹出的 " 添加类 " 对话框 , 输入 类名 Student , 就会自动生成 Student.h Student.cpp 的 头文件 源码文件名称 ; 生成的 Student.h...__Student_H_ C++ 可以都使用 ; 生成的默认类只有一个类名 , 没有其它内容 ; class Student { }; 4、确保头文件包含一次 确保头文件包含一次的方法 : C++...Student { }; C 语言 : C 语言中 , 使用 #ifndef _Student_H 的方式 , 确保头文件只被包含一次 ; #ifndef __Student_H_ #define _

    40030

    内联变量——保证变量唯一性的利器

    code using globalVar 头文件的变量globalVar会在file1.cppfile2.cpp中分别创建实例,出现重定义的链接错误,MSVC的错误为LNK2005LNK1169...内联变量 使用 inline 关键字可以将变量声明为内联变量,多个源文件包含该头文件时,编译器只会创建一个该变量的实例。...头文件定义全局变量,保证变量定义的唯一性 // constants.h #ifndef CONSTANTS_H #define CONSTANTS_H inline constexpr double...不要在多个源文件定义相同的内联变量:虽然编译器只会保留一个实例,但仍然不建议多个源文件定义相同的内联变量,以避免混乱不必要的复杂性。...总结 内联变量是 C++17 新增的特性,用于解决头文件变量多实例化的问题。通过使用inline将变量声明为内联变量,可以确保多个源文件只有一个变量实例,避免了链接时的重定义错误。

    9710
    领券