Хорошо, переформулировано и объединено из Процесс C ++ завершен из-за путаницы статуса 3 в один файл с минимальным кодом, заменив мои ссылки ‘log’ на ‘cout’, печатая на консоль вместо файла. Я запустил его с помощью компилятора code :: blocks и получил другую ошибку, но для той же строки [‘log’ не был объявлен в этой области]. Он просто закрывает программу со статусом 3, когда у меня есть классы в их собственных файлах.
Я уже сталкивался с ошибкой в области видимости, исправил ее самостоятельно и подумал, что понял ее, но думаю, что нет …
#include <iostream>
#include <string> // Doesn't complain if this is not present...
using namespace std;
//------------------------------------------------------------
class Logfile {
public:
bool LACT; // Is log file active?
string value; // Data to be entered
Logfile();
~Logfile();
void entry(string value); // Make an entry
};
Logfile::Logfile() { // Constructor
LACT = true;
cout << "OPENED\n";
}
Logfile::~Logfile() {
cout << "CLOSED\n";
}
void Logfile::entry(string value) {
if ( LACT ) cout << value << endl;
}
//--------------------------------------------------
class Engine { // Constructor contains only code for this class right now
public :
Engine();
};
В этой строке компилятор зависает и выдает ошибку:
Engine::Engine() {
log.entry("Engine constructed"); // !Problem line!
}
Я на правильном пути, думая, что проблема в том, что я неправильно вызываю метод класса существующего объекта из другого класса?
//--------------------------------------------------
int main()
{
Logfile log;
Engine engine;
cout << "Hello world!" << endl;
return 0;
}
Когда я «//» рассматриваемой строки, все работает нормально, и консоль печатает ОТКРЫТО, Hello World !, ЗАКРЫТО. Спасибо за ваше терпение и время, так как я уверен, что это гораздо проще — и для новичка — чем кажется мне.
—
Моей первоначальной целью задать этот вопрос было (теперь я понимаю) получить глобально объявленный объект, доступный из любого файла * .cpp в многофайловой программе. Я только что нашел этот ответ: http://www.cplusplus.com/forum/beginner/3848/, в случае, если это может быть полезно для кого-либо еще с подобной проблемой.
log
а также engine
полностью отделены. Ни один из них не имеет доступа к другому по своей сути.
Если ты хочешь engine
чтобы иметь доступ к экземпляру Logfile
Вы можете, например, передать его в engine
через сеттер или через Engine
конструктор:
Engine::Engine(Logfile& log) {
log.entry("Engine constructed");
}
Есть альтернативы, где вы можете иметь глобальный экземпляр Logfile
(выходит за рамки main
). Вообще глобальные переменные — плохая идея; Время жизни переменных должно быть уменьшено до минимально возможного объема. Тем не менее, файл журнала может квалифицироваться как разумное исключение из этого правила.
Чтобы объяснить немного дальше, вы можете использовать синглтон для файла журнала. Использование синглетонов — очень спорный вопрос; просто ищите синглтоны или дважды проверяйте блокировку, и вы найдете множество дискуссий об опасностях.
Однако с появлением C ++ 11 все стало намного безопаснее. Новый стандарт гарантирует, что инициализация локального статического объекта является потокобезопасной. Это позволяет нам сделать что-то вроде следующего:
class Logfile {
public:
static Logfile& instance();
void entry(const string& value) { cout << value << '\n'; }
private:
Logfile() { cout << "OPENED\n"; }
~Logfile() { cout << "CLOSED\n"; }
};
Logfile& Logfile::instance() {
static Logfile log_file;
return log_file;
}
Обратите внимание, что конструктор теперь является закрытым. Единственный способ получить Logfile
через instance()
функция, и так как она имеет локальную статическую Logfile
, когда-нибудь будет только один этот экземпляр.
Затем вы можете использовать его внутри Engine()
лайк:
Engine::Engine() {
Logfile::instance().entry("Engine constructed");
}
Вы все еще должны быть осторожны здесь, хотя. Например, на данный момент в VC2012 до сих пор не реализована поточная инициализация локальной статики, как того требует C ++ 11.
Вы должны сообщить классу Engine, где находится объект журнала. Так что вам нужно немного изменить свой код:
class Engine { // Core system, contains main loop
public :
Engine(Logfile& log);
private:
Logfile& log_;
};
Engine::Engine(Logfile& log):log_(log)
{
log_.entry("Engine constructed");
}
Теперь вы называете это из основного:
int main(int argc, char *argv[])
{
Logfile log;
Engine engine(log);
return 0;
}
Кстати: вы на самом деле не используете string value;
член класса Logfile, вы можете рассмотреть возможность его удаления.