重定义错误

重定义错误

参考 https://blog.csdn.net/yychentracy/article/details/81410610
参考 https://bbs.csdn.net/topics/391011740

文章目录

  • 重定义错误
  • 1. 常见的重定义错误
    • 1.1 文件内重定义
    • 1.2 工程内重定义
  • 2. 内部包含卫哨

重复定义是指编译时 同一个定义多次给出 或者连接时出现多个外部符号(外部函数和全局变量在不同实现文件中重复定义)。

1. 常见的重定义错误

重定义错误可以分为 文件内重定义工程内重定义。先说文件内重定义

1.1 文件内重定义

//类的重定义
class MyClass{}; //虽然没有定义任何函数和成员,但它是定义而不是声明,
class MyClass{}; //注意和class MyClass;的区别
//变量重定义
int x = 10;
int x = 10;

//函数重定义
void func(){}
void func(){}

上面展示的都是重定义错误,看起来有点蠢,谁会在同一个文件里这么直白地重复定义两个完全相同的东西呢?

如果你的定义是在 types.h 里面,而 a.c 和 b.c 又都包含了 types.h , main.c 再包含 a 和 b 两个文件 ,那么在 main,c 里面就有两份定义存在,错误便产生了。

更好的做法是不要在头文件中定义任何变量和函数,只保留它们的声明。

如果你非要在头文件内进行定义怎么办,解决办法就是 内部包含卫哨,这个后面说。

1.2 工程内重定义

工程通常是包含多个源文件的,如果你在一个源文件里定义一个变量(类或者函数),在另一个源文件做同样的定义,那就在链接时就会报错。

为什么要特别说源文件,因为头文件最后也是会被包含到源文件里,最终形成编译单元的是源文件。

2. 内部包含卫哨

内部包含卫哨只能解决文件内重定义文件,不能解决工程内重定义。

#ifndef TYPES_H
#define TYPES_H
//函数声明
//函数定义,(定义最好不要写在头文件)
//……
#endif

上面展示的就是常见的内部包含卫哨,作用就是防止头文件重复包含。

下面分析下原理:

假设 main.c 包含两次 types.h,第一次 include 时没有定义 TYPES_H 宏,那么就定义 TYPES_H,然后将函数声明和定义全部拷贝到 main.c 中;第二次 include 时宏已经存在,直接 endif ,什么都不做。

因此,内部包含卫哨只能解决文件内的重定义问题,当除了 main.c 之外还有其他源文件也包含 types.h 时,types 中的函数声明和定义也会存在于那个源文件,就会产生工程内重定义问题。

最好的做法就是不要再头文件中进行任何定义,只做声明。

在此基础上,如果出现工程内重定义时,把重复的删去即可。

你可能感兴趣的:(C,C++)