C++编译报错‘Materia未在当前作用域声明’问题求助
报错原因
- 头文件展开顺序错误:main.cpp中先引入了
funciones.h,之后才定义Materia类。预处理器处理代码时会先把funciones.h的内容完全展开到引入位置,此时funciones.h里的bool grabarEnDisco(Materia);声明用到了还未定义的Materia类型,自然会触发未声明的错误。 - 额外的不规范写法:你直接把函数实现写在了
.h头文件中,后续如果有多个源文件引入该头文件会触发重复定义错误,即使当前单文件场景下不报错也不符合C++项目的规范。
修复方案
步骤1:抽离Materia类到独立头文件
新建Materia.h文件,放入Materia类的完整定义,添加头文件保护:
#ifndef MATERIA_H_INCLUDED #define MATERIA_H_INCLUDED #include <cstring> #include <iostream> using namespace std; class Materia{ private: int nroMateria; char nombreMateria[40]; int cantAlumnos; int cantDocentes; public: void Cargar(){ int nro; cout<<"NUMERO DE MATERIA: "; cin>>nro; setNroMateria(nro); cout<<"NOMBRE DE MATERIA: "; cin.ignore(); cin.getline(nombreMateria,35); cout<<"CANTIDAD DE ALUMNOS: "; cin>>cantAlumnos; cout<<"CANTIDAD DE DOCENTES: "; cin>>cantDocentes; } void Mostrar(); void setNroMateria(int nm){if(nm>0)nroMateria=nm;} void setNombreMateria(const char *nm){strcpy(nombreMateria,nm);} int getNroMateria(){return nroMateria;} char *getNombreMateria(){return nombreMateria;} }; void Materia::Mostrar(){ cout<<"NUMERO DE MATERIA: "; cout<<nroMateria<<endl; cout<<"NOMBRE DE MATERIA: "; cout<<nombreMateria<<endl; cout<<"CANTIDAD DE ALUMNOS: "; cout<<cantAlumnos<<endl; cout<<"CANTIDAD DE DOCENTES: "; cout<<cantDocentes<<endl; cout<<endl; cout<<"-------------------------"<<endl; cout<<endl; } #endif // MATERIA_H_INCLUDED
步骤2:修改funciones.h仅保留声明
清空funciones.h中原有的函数实现,只保留函数声明,并且在开头引入Materia.h:
#ifndef FUNCIONES_H_INCLUDED #define FUNCIONES_H_INCLUDED #include "Materia.h" void CargarMateria(); void MostrarMateria(); bool grabarEnDisco(Materia); #endif // FUNCIONES_H_INCLUDED
步骤3:抽离函数实现到独立源文件
新建funciones.cpp文件,放入原来funciones.h里的所有函数实现:
#include <iostream> #include <cstdio> #include "funciones.h" using namespace std; void CargarMateria(){ Materia obj; obj.Cargar(); if(grabarEnDisco(obj)==true){ cout<<"REGISTRO AGREGADO"; }else { cout<<"NO SE PUDO AGREGAR EL REGISTRO"; } cout<<endl; } void MostrarMateria(){ FILE *pMateria; Materia obj; pMateria = fopen("materias.dat", "rb"); if(pMateria == NULL){ cout<<"ERROR DE ARCHIVO"; return; } fread(&obj,sizeof(Materia),1,pMateria); fclose(pMateria); obj.Mostrar(); } bool grabarEnDisco(Materia obj){ FILE *pMateria; pMateria = fopen("materias.dat", "wb"); if(pMateria == NULL){ cout<<"ERROR DE ARCHIVO"; return false; } fwrite(&obj,sizeof(Materia),1,pMateria); fclose(pMateria); return true; }
步骤4:修改main.cpp删除冗余定义
删掉main.cpp里的Materia类定义,仅保留头文件引入和main函数即可:
#include <iostream> #include <cstdlib> #include <cstring> #include "Materia.h" #include "funciones.h" using namespace std; int main(){ int opc; while(true){ system("cls"); cout<<"MENU ARTICULOS: "<<endl; cout<<"1. CARGAR MATERIAS: "<<endl; cout<<"2. MOSTRAR MATERIAS: "<<endl; cout<<"0. SALIR DEL PROGRAMA: "<<endl; cout<<"SELECCIONE UNA OPCCION: "<<endl; cin>>opc; system("cls"); switch(opc){ case 1: CargarMateria(); break; case 2: MostrarMateria(); break; case 0: return 0; break; } system("pause"); } return 0; }
额外优化建议
- 你当前
grabarEnDisco函数使用wb模式打开文件,每次写入都会清空原有内容,若需要实现多记录追加存储,将打开模式改为ab即可。 - 不建议在头文件中使用
using namespace std,容易引发全局命名空间污染,后续优化可以去掉头文件里的该语句,将std前缀补全到对应的标准库调用前。
内容的提问来源于stack exchange,提问作者matuco1998
相关产品推荐
相关产品推荐

