What's wrong with my file logger class in C++? - c++

I'm trying to summarize some experimental results in a file.
The results are generated in various C++ classes and files.
I want them to all write to the same file.
For this reason it would be conventient to have a header that defines everything, and then I can just include it in the files that need to write to it. I should be a singleton, so it is not tried to open the same file twice.
It looks like this:
#ifndef FILELOGGER_H
#define FILELOGGER_H
#include <fstream>
class FileLogger{
std::ofstream *logfile;
static FileLogger *s_instance;
FileLogger()
{
logfile = new std::ofstream();
logfile->open("~/results/experiments.txt", std::ios_base::app);
}
~FileLogger()
{
std::cout << "Destructor of logger called" << std::endl;
if(s_instance)
{
logfile->close();
delete logfile;
delete s_instance;
}
}
public:
static std::ofstream *instance()
{
if (!s_instance)
{
s_instance = new FileLogger();
}
std::cout << "got logger" << std::endl;
return s_instance->logfile;
}
};
FileLogger *FileLogger::s_instance = 0;
#endif // FILELOGGER_H
I would now think that in another file I just do:
#include "FileLogger.h"
and then use
*FileLogger::instance() << "Testoutput" << std::endl;
to write to the file. However, if I try it out, the file is not created; if I create it per hand nothing is written to it.
I do get the output of "got logger", that is called when the logger is accessed via the instance method.
I also noticed that the destructor is never called.
Why is this not working / Is this bad style?

This code
logfile->open("~/results/experiments.txt", std::ios_base::app);
tries to open a file with the literal name ~/results/experiments.txt. Tilde expansion to your home directory is done by your command shell (probably bash). You need to use the actual name of your home directory, for example:
logfile->open("/home/yourusername/results/experiments.txt", std::ios_base::app);

Let go of the 'header' trick.
Just declare a class in a header, implement it in a cpp file, and use a static counter or static boolean to prevent multiple instantiations.
I think that's much simpler than this header-only singleton magic.

Related

While seperating classes, using a function in cpp file causes errors

So i just learned how to seperate classes and the youtube totourial is stressing on doing this alot, here's the link
https://www.youtube.com/watch?v=NTip15BHVZc&list=PLAE85DE8440AA6B83&index=15
My code is the exact same as his, and in the cpp file theres this thing:
mainClass::myfunction; (mainclass is the name of my class, myfunction is my function)
when i try to execute my program, it gives an error:
unidentified reference to 'mainClass::myfunction()'
here's my main.cpp file code:
#include <iostream>
#include "mainclass.h"
using namespace std;
int main()
{
mainClass bo;
bo.myfunction();
return 0;
}
here's my mainclass.h code:
#ifndef MAINCLASS_H
#define MAINCLASS_H
class mainClass
{
public:
myfunction();
};
#endif // MAINCLASS_H
my mainclass.cpp:
#include "mainclass.h"
#include <iostream>
using namespace std;
mainClass::myfunction()
{
cout << "I am a banana" << endl;
}
I don't know much about these so could you just tell me what the errors here are, because i copied everything correctly from the guy's totourial but still it doesn't work
P.S: this happens to me alot, i understand everything, nothing works, i copy everything, nothing works, and then i literally do exactly what the person is doing, still nothing works on all three of PC's, so i dont think the problem is with the devices lol
I doubt you completely copied and pasted that code because I'm fairly sure a teacher shouldn't be teaching having functions without a specified return type, but let's jump into it anyways...
Possibility #1
You meant to create a constructor for the class. In that case, please make sure the constructor function has the same name as the class. Also, you can't call it through .mainClass(), as it is a constructor.
class mainClass
{
public:
mainClass();
};
mainClass::mainClass()
{
cout << "I am a banana" << endl;
}
Possibility #2 You meant to create the class member function myfunction. You really should be specifying what return type your function is of. Some compilers will auto-assume int return type, and so the function you created is int myfunction();, but you really should be specifying it as void myfunction(); since you didn't return anything. Addl. info: Does C++ allow default return types for functions?
Next, change how you are giving the definition, by adding the return type.
void mainClass::myfunction()
{
cout << "I am a banana" << endl;
}
Possibility #3 Those should work, but another issue is that you might not have linked mainclass.cpp, so there is no definition available. In code blocks, right click on the project name and hit Add Files, then add the mainclass.cpp so the linker can define mainClass::myfunction().
To troubleshoot if the mainclass.cpp is being built with the project, try adding
#error I'm included! to the file mainclass.cpp after #include "mainclass.h". If you get an error I'm included!, then it is linked and you can remove the #error.

how to write into a single file (create from stream class) from two different files using ofstream

I am using ofstream to write into a file.
ofstream myfile;
myfile.open("test.txt",ios::app);
Now, I want this variable "myfile" to be used by two different files.
eg:example.cc and example1.cc
I have declared 'myfile' in example.cc file, and after a function call when the call goes to example1.cc, I am using the same name 'myfile ' to write into the same file test.txt.
But I am getting error as
#example1.cc 'myfile' was not declared in the scope
I know that its not in scope, But as I am new to cpp , I don't know how to make a same file available to two different file.
If I declare a file in example1.cc than it will become a new file rite?
I think that I have finally understood what you are trying to achieve. You want to have access to one stream from two different source files(translation units). I assume that due to the fact that you are new to C++, I should suggest the simplest solution. Please do not assume that it is the best one, as it has a lot of caveats. We have project that contains three source files: foo1.cpp, foo2.cpp, main.cpp:
File foo1.cpp
#include <fstream>
extern std::ofstream logger;
void foo1()
{
logger << "Foo1 started" << std::endl;
//some stuff
logger << "Foo1 finished" << std::endl;
}
File foo2.cpp
#include <fstream>
extern std::ofstream logger;
void foo2()
{
logger << "Foo2 started" << std::endl;
//some stuff
logger << "Foo2 finished" << std::endl;
}
File main.cpp
#include <fstream>
#include <iostream>
std::ofstream logger;
void foo1();
void foo2();
int main()
{
logger.open("./data.txt", std::ios::app);
foo1();
foo2();
logger.close();
}
This code would hope fully compile and after execution there will be a file data.txt with this content:
Foo1 started
Foo1 finished
Foo2 started
Foo2 finished
I think that the most interesting for you should be the fourth line from main.cpp and third lines in foo1.cpp and foo2.cpp.
The fourth line in main.cpp, because the logger is declared outside main function, this allows other function to reach the logger and use it. This is true not only for the functions in this .cpp file. The compiler will put the address to this variable in symbol table for .o file, and this is exactly what was my intention. You may try to add static keyword before it and see what will happen. (it will disable this behavior)
Third lines from foo1.cpp and foo2.cpp informs the compiler that there will be such a variable(it will now now its name and type) in the symbol table of some .o(main.o in our case). The compiler will generate the code that uses such a variable and will place in the symbol table that this file need such variable to be provided(aka. undefined symbol).
If you manage to understand this you may also use your own header file. There is some kind of duplication in this "project". The first three lines of foo1.cpp and foo2.cpp are exactly the same. You may want to use header file to reduce this.
logger.hpp:
#include <fstream>
extern std::ofstream logger;
foo1.cpp:
#include "logger.hpp"
void foo1()
{
...
foo2.cpp
#include "logger.hpp"
void foo2()
{
...
The headers files are usually used just for this, to keep the interface to other source files in one place, additionally to in-line function and templates. If you will ever think to use it for something else, please think again

Easier way to implement .cpp file

Im just curious, but is there a way to make it so you don't have to put a class name before a function? here's an example:
HelloWorld.h
class HelloWorld{
HellowWorld();
};
HelloWorld.cpp
#include "HellowWorld.h"
HelloWorld::HelloWorld(){}
I'm wondering if there is a way to be able to have the .cpp file look like the following.
HelloWorld.cpp < New Version
#include "HellowWorld.h"
HelloWorld(){}
Functions do not have to be defined in the class, only declared.
I prefer to define the method contents in a separate file. This reduces the chance of other files compiling because I made a change to the content of a function.
Hello.hpp:
class HelloWorld
{
HelloWorld(); // Declares the constructor
};
Hello.cpp:
#include "Hello.hpp"
#include <stdio>
HelloWorld ::
HelloWorld()
{
std::cout << "Hello World\n";
}
Now I can make a change to the HelloWorld constructor and not worry about changing the header file. Because if the header file changes, all the source files that include Hello.hpp will need to be recompiled.
Edit 1: Reducing "HelloWorld::"
You can remove the HelloWorld:: part by incorporating a using statement:
#include "Hello.hpp"
#include <stdio>
using HelloWorld;
HelloWorld()
{
std::cout << "Hello Mars\n";
}
If this is a class member method then no, there is no way (apart from impractical showcase-only magic like don't put ; in .h but finish class definition in .cpp) to avoid class specification.

How to access non member functions that are in a seperate file (.cpp) than main

So I am working on my first multiple file, non-toy, c++ project. I have a class that represents a multi-spectral image and all the information that goes along with it.
My problem is how to design the part of the program that loads and object of this class with a file from disk!
I don't think I need a class for this. Would switching to a functional approach be better for the file loading. This way I can have just a source file (.cpp) that has functions I can call while passing in pointers to the relevant objects that will be updated by the file accessed by the function.
I don't think static functions are what I want to use? As I understand it they(static functions) are for accessing static variables within a class, aren't they?
If I go the functional route, from main(), how do I access these functions? I assume I would include the functions .cpp file at the beginning of the main() containing file. From there how do I call the functions. Do i just use the function name or do I have to pre-pend something similar to what you have to pre-pend when including a class and then calling its methods.
Here is some example code of what I have tried and the errors I get.
OpenMultiSpec.cpp
#include <iostream>
void test(){
std::cout << "Test function accessed successfully" << std::endl;
}
main.cpp
int main(){
test();
return 1;
}
The error says " 'test' was not declared in this scope "
OpenMultiSpec.h
void test();
main.cpp
#include "OpenMultiSpec.h"
int main(){
test();
return 1;
}
If they're in two separate files, and in your case, one being a header, use
#include "OpenMultiSpec.h"
If you decide to only use one file (as your comment says above), you won't need #include for your header file. Just place your function declaration anywhere before you call it.
#include <iostream>
void test() {
std::cout << "Test function accessed successfully" << std::endl;
}
int main() {
test();
return 1;
}

How to implement a Singleton in an application with DLL

I have an application (in MS Visual Studio) that contains 3 projects:
main (the one that contains the main function)
device (models some hardware device)
config (contains some configuration for both other projects)
So the dependency graph is:
main depends on device, which depends on config
main depends on config
The config project contains a Singleton, which holds some configuration parameters.
I decided to turn the device project into a DLL. When i did this, it seems that i got two instances of the Singleton in the config project! I guess this is a classic problem, which might have a good solution. So how can i fix this?
I reproduced the problem with the following (relatively small) code. Of course, in my case there are some 30 projects, not just 3. And i would like to make just 1 DLL (if possible).
// config.h
#pragma once
#include <string>
#include <map>
class Config
{
public:
static void Initialize();
static int GetConfig(const std::string& name);
private:
std::map<std::string, int> data;
};
// config.cpp
#include "config.h"
static Config g_instance;
void Config::Initialize()
{
g_instance.data["one"] = 1;
g_instance.data["two"] = 2;
}
int Config::GetConfig(const std::string& name)
{
return g_instance.data[name];
}
// device.h
#pragma once
#ifdef _DLL
#define dll_cruft __declspec( dllexport )
#else
#define dll_cruft __declspec( dllimport )
#endif
class dll_cruft Device
{
public:
void Work();
};
// device.cpp
#include "device.h"
#include <iostream>
#include "config.h"
void Device::Work()
{
std::cout << "Device is working: two = " << Config::GetConfig("two") << '\n';
}
// main.cpp
#include <iostream>
#include "config.h"
#include "device.h"
int main()
{
std::cout << "Before initialization in application: one = " << Config::GetConfig("one") << '\n';
Config::Initialize();
std::cout << "After initialization in application: one = " << Config::GetConfig("one") << '\n';
Device().Work();
std::cout << "After working in application: two = " << Config::GetConfig("two") << '\n';
}
Output:
Before initialization in application: one = 0
After initialization in application: one = 1
Device is working: two = 0
After working in application: two = 2
Some explanations on what the code does and why:
Main application starts
The first print is just to show that the singleton is not initialized yet
Main application initializes the singleton
The first print shows that the initialization worked
Main application starts the "hardware device"
Inside the DLL, the singleton is not initialized! I expect it to output two = 2
The last print shows that the singleton is still initialized in main application
When I ran into this same problem I solved it by creating another DLL whose sole purpose is to manage the singleton instance. All attempts to get a pointer to the singleton call the function inside this new DLL.
You can decide where singleton should reside and then expose it to other consumers.
Edited by OP:
For example, i want that the config instance appear only in the EXE (not DLL).
Turn the instance into a pointer
static Config* g_instance;
Add a separate initializing function to device's exported functions:
void InitializeWithExisting(Config* instance) {g_instance=instance;}
After initializing the singleton normally, use the second initialization:
Config::Initialize();
Config::InitializeWithExisting();
I believe that defining and accessing singleton instance this way might solve your problem:
Config& getInstance()
{
static Config config;
return config;
}
This way you also don't need to have (and call) the Initialize method, you can use constructor for initializing, that will be called automatically when you call getInstance for the first time.