3

Подскажите, как реализовать следующее. Есть примерно 8 пар .h и .cpp файлов, в одном из них есть функция, которая считывает введённые данные. Мне надо запомнить эти данные, чтобы я мог в остальных файлах ими пользоваться. Как это реализовать? В интернете что-то нашел про extern, но так и не получилось ничего.

2 ответа 2

8

Везде, где собираетесь использовать глобальную переменную, включите её декларацию (declaration), например, пусть она будет в каком-то общем хедере. А только в одном из модулей cpp определите эту переменную (definition)

File 1:

int GlobalVariable;         // определение в одном файле. здесь переменная "будет жить"
void SomeFunction();
void AnotherFunction();
int main() {
    GlobalVariable = 1;
    SomeFunction();
    AnotherFunction();
    return 0;
}

File 2:

extern int GlobalVariable;  // декларация во всех пользующихся файлах
void SomeFunction() {
    ++GlobalVariable;
}

File 3:

extern int GlobalVariable;  // декларация во всех пользующихся файлах
void AnotherFunction() { 
    --GlobalVariable;
}
4
  • Спасибо все заработало! А если мне так надо создать еще и тип char, то я в главном файле делаю так: char* ci[size], а уже во всех других так: extern char* ci[size]. Это правельно? ведь сам массив я не могу передовать значит просто выделяю место и создаю указатель? 6 апр 2011 в 16:31
  • Смотря что хотите получить. char* ci[size] - это будет массив на size элементов указателей на строки. Если же хотите работать со строкой, то нужно char ci[size]. Да, в других модулях нужно будет написать extern char* ci[size] или extern char ci[size] соответственно. Касательно передачи массива напоминаю, что имя массива - указатель на начало массива.
    – gecube
    6 апр 2011 в 17:51
  • Мне нужно работать со строкой. Если я объявляю в клавном файле вот так: char cI[BUF_SIZE]; то программа не компилируется и выдает следующую ошибку: globVars.obj : error LNK2005: "char * cI" (?cI@@3PADA) already defined in Diplom.obj объявляю в другом файле переменную следующим образом(extern char cI[BUF_SIZE]; и пробывал так еще extern char* cI[BUF_SIZE];), но если я в главном файле делаю так: char* cI[BUF_SIZE]; то все компилируется, но как я понял это будет не то что мне надо. :( подскажите что не так? 7 апр 2011 в 6:52
  • все решилось спасибо, сам затупил. 7 апр 2011 в 7:09
3

Вообще ИМХО, раз уж задачка решается на C++, то лучше сразу проектировать правильно, ибо глобальные переменные - всё-таки зло. ;) А именно сделать следующее:

  1. В одном исходнике создать класс, который управляет всем - Manager;
  2. В другом реализовать класс, который считывает данные и хранит их - DataReader;
  3. В остальных - прочую логику работы, которая реализует всё, что вам нужно.

Правильная архитектура решит множество проблем. Пример:

file "data_reader.h"

struct MyData 
{
    // ... мои данные ...
    int my_field;
};

class DataReader {
    MyData my_data;
public:
    bool ReadData( const std::string& data_file )
    {
        // ... считываем входные данные в my_data ...
        return true;
    }
    // по требованию использующей стороны отдаём данные
    TMyData& Data()
    {
        return my_data;
    }
};

file "manager.h"


 #include "data_reader.h"
 #include "mylogic1.h"
 #include "mylogic2.h"
 // ...
 #include "mylogic8.h"
 #include <string>

class Manager { DataReader data_reader; MyLogic1 my_logic1; MyLogic1 my_logic2; // ... MyLogic1 my_logic8; bool init_ok; public: // В конструкторе менеджера сказать всем классам, реализующим мою логику, // откуда брать прочитанные данные Manager(const std::string& data_file) : my_logic1 (data_reader) , my_logic2 (data_reader) // ... , my_logic8 (data_reader) { init_ok = data_reader.ReadData(data_file); } // bool IsInitOk() { return init_ok; } // void Work() { my_logic1.Work(); my_logic2.Work(); // ... my_logic8.Work(); } };

Реализация моей логики "mylogic1.h"

#include "data_reader.h"

class MyLogic1 { DataReader& dr; public: MyLogic1( TDataReader& data_reader ) : dr (data_reader) {} // void Work() { // ... моя логи работы; когда мне нужны считанные данные, делаю вот так: printf("Readen data: %dn", dr.Data().my_field); // (!) Так нам не нужно будет использовать никаких глобальных переменных ... } };

files mylogic2.h ... mylogic8.h


// Прочие файлы, с реализацией моей логики; они также используют DataReader::Data(), 
// чтобы получить доступ к считанным данным. 

file "main.cpp"

#include "manager.h"

int main(int argc, char* argv[]) { // Инициализируем менеджер Manager manager("my.dat"); // Если инициализация прошла успешно, работаем if (manager.IsInitOk()) { manager.Work(); return 0; } // Ошибка return 1; }

Преимуществ реализации без глобальных переменных множество. Главные из них такие:

  • Не будет путаницы имён переменных, когда вы будете разрабатывать сложную программу;
  • Вы сами можете выбрать, где вам хранить ВСЕ данные "скопом" (экземпляр класса Manager): на стеке, на куче или вообще сделать её глобальной;
  • Можно создать множество менеджеров (в зависимости от задачи) и манипулировать ими, как угодно;
  • и многое другое... :)

Ну + предлагаю вообще почитать про паттерны проектирования C++, ибо то, что я здесь наваял - это их "велосипедная" смесь. :)

Ваш ответ

By clicking “Отправить ответ”, you agree to our terms of service and acknowledge you have read our privacy policy.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками или задайте свой вопрос.