Почему выдаёт ошибку и как её исправить?
Ошибка:
In file included from C:\Users\Kirill Pukhov\CLion\untitled\data.h:5:0, from C:\Users\Kirill Pukhov\CLion\untitled\main.cpp:2: C:\Users\Kirill Pukhov\CLion\untitled\subjects.h: In function 'void newSubject()': C:\Users\Kirill Pukhov\CLion\untitled\subjects.h:42:17: error: 'saveData' was not declared in this scope saveData(sub); ^ mingw32-make.exe: *** [CMakeFiles/untitled.dir/main.cpp.obj] Error 1
CMakeList.txt
cmake_minimum_required(VERSION 3.12)
project(untitled)
set(CMAKE_CXX_STANDARD 17)
add_executable(untitled main.cpp subjects.h data.h)
main.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <conio.h>
#include "data.h"
#include "subjects.h"
int main() {
setlocale(LC_ALL, "");
std::cout << "Нажмите 1, что-бы загрузить список предметов \n";
std::cout << "Нажмите 2, что-бы добавить предмет в список \n";
std::cout << "Нажмите 3, что-бы закрыть приложение \n";
switch(getch()) {
case '1':
break;
case '2':
newSubject();
break;
case '3':
break;
default :
std::cout << "Ошибка \n";
}
return 0;
}
data.h
#ifndef UNTITLED_DATA_H
#define UNTITLED_DATA_H
#include <iostream>
#include <fstream>
#include "subjects.h"
void loadData(subject sub) { // Считывание данных из файла
std::ifstream fin(sub.takeNameOfSubject() + ".data");
if(!fin.is_open()) {
std::cout << "Warning of opening the file: " + sub.takeNameOfSubject() + ".data";
} else {
fin.read((char*)&sub, sizeof(sub));
}
fin.close();
}
void saveData(subject sub) { // Запись данных в файл
std::ofstream fout(sub.takeNameOfSubject() + ".data");
if(!fout.is_open()) {
std::cout << "Warning of opening the file: " + sub.takeNameOfSubject() + ".data";
} else {
fout.write((char*)&sub, sizeof(sub));
}
fout.close();
}
#endif //UNTITLED_DATA_H
subjects.h
#ifndef UNTITLED_SUBJECTS_H
#define UNTITLED_SUBJECTS_H
#include <iostream>
#include <vector>
#include "data.h"
class subject {
public:
subject(std::string nameOfSubject) { // Конструктор
this->nameOfSubject = nameOfSubject;
}
~subject() { // Деконструктор
}
void takeMarks(std::vector<int> marks) { // Вывести оценки
for(auto &iter : marks) {
std::cout << iter << " ";
}
std::cout << std::endl;
}
int takeAverageNum(std::vector<int> marks) { // Получить среднее арефметическое
int sum = 0;
for(int &mark : marks) {
sum += mark;
}
return (sum / (marks.size() + 1));
}
std::string takeNameOfSubject() { // Получить имя предмета
return nameOfSubject;
}
private:
std::string nameOfSubject; // Имя предмета
};
void newSubject() { // Создание нового предмета
std::string nameOfSubject;
std::getline(std::cin, nameOfSubject);
subject sub(nameOfSubject);
saveData(sub);
}
#endif //UNTITLED_SUBJECTS_H
Краткий ответ. Перенесите тела функций в cpp файлы.
Длинный ответ. Для начала посмотрим, что делает #include
- а он просто вставляет содержимое файла. Потом следующая часть препроцессора - исключение текста (да, еще текста, а не кода) по условиям (#ifdef
и коллеги). Если Вы аккуратно все это сделаете (или попросите gcc с параметром -E
), то увидите, что тело и объявление функции SaveData находится ниже, чем использование в subjects.h. А компилятор не умеет заглядывать вниз.
Когда же все тела функций будут вынесены, то в заголовочных файлах будет только обявление функций и все станет хорошо.
Но можно сделать "хак ногой" (никогда не делайте так в реальном проекте, только в учебных целях).
Перед функцией newSubject
добавить одну строку с объявлением сигнатуры функции
void saveData(subject sub);
и теперь компилятор будет счастлив. Но, возможно, нужно будет и ряд других функций попереносить.
P.S. Покажу на примере data.h
data.h
#ifndef UNTITLED_DATA_H
#define UNTITLED_DATA_H
#include "subjects.h"
// Считывание данных из файла
void loadData(subject sub);
// Запись данных в файл
void saveData(subject sub);
#endif //UNTITLED_DATA_H
data.cpp
#include <iostream>
#include <fstream>
#include "data.h"
#include "subjects.h"
void loadData(subject sub) { // Считывание данных из файла
std::ifstream fin(sub.takeNameOfSubject() + ".data");
if(!fin.is_open()) {
std::cout << "Warning of opening the file: " + sub.takeNameOfSubject() + ".data";
} else {
fin.read((char*)&sub, sizeof(sub));
}
fin.close();
}
void saveData(subject sub) { // Запись данных в файл
std::ofstream fout(sub.takeNameOfSubject() + ".data");
if(!fout.is_open()) {
std::cout << "Warning of opening the file: " + sub.takeNameOfSubject() + ".data";
} else {
fout.write((char*)&sub, sizeof(sub));
}
fout.close();
}
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Виртуальный выделенный сервер (VDS) становится отличным выбором
Нужно, чтобы программа переименовывала окно второй программыУкажите пожалуйста на ошибку:
На трех указателях ясно, но ни как не могу придумать как реализовать вектор на одном указателе, не задействовав для хранение оставшихся двух...