Почему выдаёт ошибку и как её исправить?

111
06 июня 2019, 23:20

Почему выдаёт ошибку и как её исправить?

Ошибка:

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
Answer 1

Краткий ответ. Перенесите тела функций в 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();
}
READ ALSO
Переименование окна другой программы SendMessege

Переименование окна другой программы SendMessege

Нужно, чтобы программа переименовывала окно второй программыУкажите пожалуйста на ошибку:

140
Проблема с выводом в файл

Проблема с выводом в файл

У меня 2 вопроса:

121
Как реализовать вектор на одном указателе?

Как реализовать вектор на одном указателе?

На трех указателях ясно, но ни как не могу придумать как реализовать вектор на одном указателе, не задействовав для хранение оставшихся двух...

141
Фон виджета в Android

Фон виджета в Android

Есть drawable, используемый в качестве фона для виджета

136