C++中重定义问题

问题阐述

写图的数据结构相关代码时,本来在同一个文件里面写了MatGraph类(图的邻接矩阵)、AdjGraph类(图的邻接表),一些图相关的算法实现和main函数。但后来认为将所有代码堆在同一个文件里不是一个好的程序结构,结构不清晰也不利于后期维护和回顾。因此准备将两个类的成员变量定义、成员函数声明分别放入.h文件中,将成员函数实现放入.cpp中,再在test.cpp中编写main函数,创建对象和调用函数。

但是真正实施的时候出现了重定义的问题,搜索各种资料尝试各种方法,搞了一个上午也没能解决。最终通过增加另一个.h文件专门用来定义常量,作业跑通了程序。在此记录一下解决问题的过程。

或许这仍然不是一个最优解决方案,希望可以有大佬指点~

我在程序中定义了两个常量MAXV和INF,分别表示图中顶点数的最大值和无穷。

const int MAXV = 100;
const int INF = 0x3f3f3f3f;

同时,两个类中都定义了容量为MAXV的数组。

//MatGraph.h文件
class MatGraph {//邻接矩阵类
public:
	int edges[MAXV][MAXV];
	int n, e;

	//创建图的邻接矩阵
	void CreateMatGraph(int a[][MAXV], int n, int e);

	//输出图
	void DispMatGraph();

	//以传入的节点号为起点广度优先遍历
	//时间复杂度为0(n+e)
	void MatGraph_BFS(int f);

};
//AdjGraph.h文件
struct ArcNode {//边节点
	int adjvex;
	int weight;
	ArcNode* nextarc;
};

struct HNode {//头结点
	string info;
	ArcNode* firstarc;
};

class AdjGraph {//邻接表类
public:
	HNode adjlist[MAXV];
	int n, e;//顶点数,边数

	//构造函数
	AdjGraph();

	//析构函数,释放邻接表指针空间
	~AdjGraph();

	//通过a、n、e创建图的邻接表
	void CreateAdjGraph(int a[][MAXV], int n, int e);

	//输出图
	void DispAdjGraph();

	//以传入的节点号为起点深度优先遍历
	int visited[MAXV] = { 0 };
	void AdjGraph_DFS(int f);


};

如果两个.h文件中同时定义常量MAXV和INF,则会报重定义的错误:

解决方式一(不适用)

在网上看见可以通过extern声明外部变量

C99中规定 :所有顶层的默认存储类标志符都是extern。

也就是extern关键字写不写都可以,因此我在MatGraph.h文件中定义了两个常量并赋初值,在AdjGraph.h文件中声明,但没有赋初值。希望编译器可以顺利连接。

但是由于C++语言规定数组长度在编译时必须有明确的值,即必须在数组定义时指定数组的长度;指定数组长度的常量表达式只能是整型字面常量或符号常量。

而在编译器连接时似乎认为AdjGraph.h中的MAXV没有被初始化,会报如下错误:

解决方式二

我尝试只在MatGraph.h文件中定义两个常量并赋初值,而在AdjGraph.h中#include “MatGraph.h”。

此时报出了如下错误:

这是因为我在test.cpp中#include “MatGraph.h”并#include “AdjGraph.h”,这样MatGraph.h就被嵌套包含,被编译多次,于是编译器报重定义的错误。

重复编译解决方式一

解决方式是在MatGraph.h的开头加上这句话:

#pragma once

意思就是这个程序无论被包含多少次,只编译一次,从而解决了重定义问题。

重复编译解决方式二

同样可以用如下预编译指令解决:

#ifndef A_H
#define A_H
//A.h的内容
#endif

意思是如果未定义A_H,就定义它;如果已定义就什么都不干。

这里A_H的标识符可以自定义。

上面两种方式的作用一样,编写.h文件时加上这几句话是一个良好的编程习惯。

虽然问题解决了,但是我仍然认为.h包含.h的方式不是特别好,因为MatGraph和AdjGraph是两个地位平等的类,并不存在一个包含另一个的关系,我却为了常量的共用而破坏了这种平等关系,程序结构不太符合逻辑。

解决方式三

我重新写了一个CONST.h,专门用来存放两个常量的定义,并在MatGraph.h和AdjGraph.h中#include “CONST.h”,程序也跑通啦!

这样我就没有破坏两个类之间的平等关系,同时实现了常量的共用~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值