c++学习笔记(1)-符号重定义

本文详细介绍了符号重定义在C++中的常见场景,包括预处理期、编译期、链接期和运行期的错误实例。同时探讨了解决符号重定义问题的不同方法,如使用static、inline、extern和const,以及命名空间的应用。
摘要由CSDN通过智能技术生成

1、引言

符号重定义(Symbol Redefinition)指的是在同一个作用域内多次定义同名标识符(包括变量、函数、类等)。符号重定义错误通常包括预处理期符号重定义,编译期符号重定义,链接期符号重定义,以及运行期符号重定义。

2、符号重定义场景

2.1、同名宏

如果在多个地方重复定义同一个宏,则会在预处理阶段导致符号重定义错误。

//file1.h
#define MAX 100

//file2.h
#define MAX 50

//main.c
#include "file1.h"
#include "file2.h"
int main() {
   return 0;
}

在这个例子中,当编译器编译 main.c 时,会发现 MAX 宏在两个头文件中都被定义了,从而导致符号重定义错误。

2.2、名称冲突

同一作用域或不同作用域内出现了相同的符号名定义,会造成编译期错误。下面是一个C++示例代码,演示了编译期符号重定义错误:

#include <iostream>
int value = 3;
int value = 5;// 错误:value重定义

int main()
{
    std::cout << value << std::endl; 
    return 0;
}

在上述代码中,我们在同一作用域中定义了两个名为value的变量,这会导致编译器无法确定应该取哪个变量的值,所以会在编译期间报错,提示符号重定义的问题。

2.3、头文件多重包含

头文件多重包含的问题是这样产生的:当一个源文件包含多个头文件时,某个头文件可能会包含一个已经包含过的头文件,导致同一个函数或变量的定义被重复包含。下面是一个示例,展示了多重包含相同的头文件引起重定义的错误:

//add.h文件
int add(int a,int b){
    return a+b;
}

//printAdd.h文件
#include<iostream>
#include"add.h>
void printAdd(int a,int b){
    std::cout<<add(a,b)<<std::endl;
}

//main.cpp文件
#include"printAdd.h"
#include"add.h"  //符号重定义
int main(){
    printAdd(1,2);
}

上述代码中,add.h文件在main.cpp内被2次包含,这就导致add()函数发生两次定义,所以会在编译期间报错,提示符号重定义的问题。

2.4、链接错误

链接重定义错误是一种常见的链接错误,通常是由于多个编译单元中出现了相同的符号定义而导致的。这种错误会在链接时被检测到,表示无法解析符号引用,因为有多个定义存在。

//a.h
int getValue();
//a.cpp
int getValue(){return 0;};

//b.h
int helgetValuelo();
//b.cpp
int getValue(){return 1;}

我们将a.cpp和 b.cpp 分别编译为目标文件a.o和b.o,并尝试将其链接到一起,会导致符号重定义错误。

2.5、运行期符号重定义

符号重定义错误通常是在编译期间被检测到的,而不是在运行时。然而,有些情况下可能会在运行时发生符号重定义错误。例如,在动态链接库或共享对象中,函数或变量可以在运行时加载和卸载。如果在两个动态链接库中定义了相同名称的函数或变量,它们可能会导致符号重定义错误。

3、符号重定义机制

c++ 采用单文件编译,在编译期间将这些文件单独编译成目标文件,然后通过链接器将它们组合成一个可执行文件。编译器在把单个源码文件编译成目标文件过程中,会检测源码中的同名符号,从而发现预处理期符号重定义,编译期符号重定义的错误。目标文件格式如下:
目标文件头ELF Header内存放有符号信息,把多个目标文件链接到一起的时候,若发现文件头内有同名符号,就会报链接期符号重定义错误。接下来看一下符号表结构:

4、解决符号重定义的方法

这里列举了6种解决符号重定义问题的方法,其中static,inline,extern,const只能用于解决链接期重定义问题;
预处理指令只用于解决编译期重定义问题;
命名空间可解决预处理期和编译期重定义问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值