How to initialize an object that declared as const on header file? - c++

I want to initialize std::ifstream object only in the main() function after declare it in the header.
Is there any way to do it in C++?
I wrote this but it's not compiling
//header.h
#include <iostream>
#include <fstream>
class class1{
static const std::ifstream fs;
};
//proj.cpp
#include "header.h"
void main(){
class1::fs("Employee.txt")
}

static variables need to be defined at global scope, not inside a function.
main should also return int not void.
A const std::ifstream doesn't make much sense as most of the methods you would need to use are non-const so wouldn't be callable on your const stream.
Fixing these issues gives:
//header.h
#include <iostream>
#include <fstream>
class class1{
static std::ifstream fs;
};
//proj.cpp
std::ifstream class1::fs("Employee.txt");
int main(){
return 0;
}
If you want to open the stream in main then you need to do:
const std::ifstream class1::fs;
int main(){
class1::fs.open("Employee.txt");
return 0;
}

Related

Using friend function correctly across multiple Classes in C++

I am trying use a friend function. The function should be a friend to all the classes that i have. But i get multiple errors some of which says incomplete type. The following are files that i have:
main.cpp
#include <iostream>
#include "my_ClassA.h"
#include "my_ClassB.h"
#include "my_ClassC.h"
#include "my_ClassD.h"
int main()
{
std::cout<<"Hello World";
my_namespace::my_ClassA object1;//this will do some computation and set everything up for object1
my_namespace::my_ClassB object2(object1);//this object2 will use object1 to further do other computation
my_namespace::my_ClassC object3(object2);
my_namespace::my_classD object4(object4);
//runComputation(object1, object2, object3, object4);
return 0;
}
my_ClassA.h
#pragma once
#include<string>
#include <vector>
//these three includes are for friend function BUT result in error incomplete type
#include "my_ClassB.h"
#include "my_ClassC.h"
#include "my_ClassD.h"
/////////////////////////////////////////////
namespace my_namespace{
class my_ClassA{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
public:
std::vector<std::string> get_vec();
};
void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
}
my_ClassA.cpp
#include "my_ClassA.h"
std::vector<std::string> my_namespace::my_ClassA::get_vec(){
return vec;
}
my_ClassB.h
#pragma once
#include<string>
#include <vector>
#include "my_ClassA.h"
#include "my_ClassC.h"
#include "my_ClassD.h"
namespace my_namespace{
class my_ClassB{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
public:
std::vector<std::string> get_vec();
my_ClassB(my_ClassA);
my_ClassB(){
;
}
};
}
my_ClassB.cpp
#include "my_ClassB.h"
std::vector<std::string> my_namespace::my_ClassB::get_vec(){
return vec;
}
my_namespace::my_ClassB::my_ClassB(my_ClassA temp_objA){
;
}
my_ClassC.h
#pragma once
#include<string>
#include <vector>
#include "my_ClassB.h"
#include "my_ClassA.h"
#include "my_ClassD.h"
namespace my_namespace{
class my_ClassC{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
my_ClassB objB;
public:
my_ClassC(my_ClassB);
std::vector<std::string> get_vec();
};
}
my_ClassC.cpp
#include "my_ClassC.h"
#include "my_ClassB.h"
std::vector<std::string> my_namespace::my_ClassC::get_vec(){
return vec;
}
my_namespace::my_ClassC::my_ClassC(my_ClassB temp_objB){
;
}
my_ClassD.h
#pragma once
#include<string>
#include <vector>
#include "my_ClassA.h"
#include "my_ClassB.h"
#include "my_ClassC.h"
namespace my_namespace{
class my_ClassD{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
my_ClassA objA;
public:
std::vector<std::string> get_vec();
};
}
my_ClassD.cpp
#include "my_ClassD.h"
std::vector<std::string> my_namespace::my_ClassD::get_vec(){
return vec;
}
I tried using the getters of each of the classes in the main.cpp. But some my classes have large size vectors,sets etc etc. So i do not want to copy them again and again. So instead i want to access the data members of the classes directly in a function called runComputation. And that function will be taking the object created as references so that copy doesn't happen inside main.cpp.
What i have is this: First i create different objects which may take the previously created object as input in main.cpp. After all the objects are created successfully, i want to run some computation on those objects. Now the problem is that i can use the getters and setters of the objects created in the main.cpp file. But the objects have large vectors and other objects inside them, and so they will be copied each time i use them in a for loop using getters. To avoid this i want to create a friend function that can take these objects as references and avoid copying. How can i resolve this ? And is there any better way of achieving this?
PS: I am aware of ADL. Will ADL be used when i write a friend declaration like friend void runComputation(someobject&); and then after the class to make this friend function visible void runComputation(someobject&);
Make a my_forwards.h header file. It contains
namespace my_namespace {
class my_ClassA;
class my_ClassB;
class my_ClassC;
class my_ClassD;
}
(or just write this manually at the top of every header file).
Now don't include my_ClassA.h in the other headers at all. If you have the body of a function in my_ClassB that requires the definition of my_ClassA, put it in a .cpp file instead of in the header.
// my_forwards.h
namespace my_namespace {
class my_ClassA;
class my_ClassB;
class my_ClassC;
class my_ClassD;
void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
}
// my_ClassA.h
#pragma once
#include<string>
#include <vector>
#include "my_forwards.h"
namespace my_namespace{
class my_ClassA{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
public:
std::vector<std::string> get_vec();
};
}
// my_ClassA.cpp
#include "my_ClassA.h"
// include other my_ClassX here if needed, after my_ClassA.h
// implementation of my_ClassA:
std::vector<std::string> my_namespace::my_Class::get_vec() {
return vec;
}
In some cases this may require declaring a destructor/constructor in a header file, and doing a my_ClassA::my_ClassA()=default; in the cpp file.
Now, your my_ClassC has a member variable of type my_ClassB. This is a case where you have to #include "my_ClassB.h" in the my_ClassC.h header file, because my_ClassC needs the definition of my_ClassB. But in most cases, either a forward declaration is good enough, or slight modification (changing a value parameter to a reference one, for example) is good enough that you don't have to cross-include the header files.
Don't use return by value to avoid copying large vectors, return const reference to access data or non-const reference to modify.
E.g., header:
#pragma once
#include<string>
#include <vector>
//these three includes are for friend function BUT result in error incomplete type
#include "my_ClassB.h"
#include "my_ClassC.h"
#include "my_ClassD.h"
/////////////////////////////////////////////
namespace my_namespace{
class my_ClassA{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
public:
// use this getter to modify inner data by reference
std::vector<std::string>& get_vec();
// use this getter to access data by const referenct
std::vector<std::string> const & get_vec() const;
};
void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
}
implementation:
#include "my_ClassA.h"
std::vector<std::string>& my_namespace::my_ClassA::get_vec() {
return vec;
}
std::vector<std::string> const & my_namespace::my_ClassA::get_vec() const {
return vec;
}
You may want to refactor classes to a chain of function calls:
// class or struct which contains intermediate state
State state;
runComputation1(&state);
runComputation2(&state);
runComputation3(&state);
runComputation4(&state);
The problem is due to circular dependency of different files. Instead of including the headers just use forward declarations for different class parameters and the issue is resolved.

shared_ptr template argument invalid

I am trying to have a static method return a shared_ptr.
It is not compiling and is giving template argument 1 is invalid.
I can not figure out why this is.
Also, stack overflow says my post is mostly code and that I should add more detail. I don't know why this is, as being concise never hurt anyone. My problem is clear cut and and can be detailed easily.
Compiler error
src/WavFile.cpp:7:24: error: template argument 1 is invalid
std::shared_ptr<WavFile> WavFile::LoadWavFromFile(std::string filename)
WavFile.cpp
#include "WavFile.h"
#include "LogStream.h"
#include "assert.h"
using namespace WavFile;
std::shared_ptr<WavFile> WavFile::LoadWavFromFile(std::string filename)
{
ifstream infile;
infile.open( filname, ios::binary | ios::in );
}
WavFile.h
#pragma once
#ifndef __WAVFILE_H_
#define __WAVFILE_H_
#include <fstream>
#include <vector>
#include <memory>
namespace WavFile
{
class WavFile;
}
class WavFile::WavFile
{
public:
typedef std::vector<unsigned char> PCMData8_t;
typedef std::vector<unsigned short int> PCMData16_t;
struct WavFileHeader {
unsigned int num_channels;
unsigned int sample_rate;
unsigned int bits_per_sample;
};
static std::shared_ptr<WavFile> LoadWavFromFile(std::string filename);
private:
WavFile(void);
private:
WavFileHeader m_header;
PCMData16_t m_data16;
PCMData8_t m_data8;
};
#endif
Change the namespace name to something else. Now it clashes with the class' name, since you are using namespace WavFile;. Simple example that illustrates the error:
#include <iostream>
#include <memory>
namespace X // changing this to Y makes the code compilable
{
class X{};
}
using namespace X; // now both class X and namespace X are visible
std::shared_ptr<X> v() // the compiler is confused here, which X are you referring to?
{
return {};
}
int main() {}
If you insist to have the namespace named as the class, then get rid of the using namespace X; and qualify the type, std::shared_ptr<WafFile::WavFile>.

C++ class termination

I have declared a class and instantiated a class in one and expected it to fire
~CLog();
But for some reason, it does not. Does anybody see any obvious errors why this could happen?
I declared the class within a void that ends, so it SHOULD fire, I think.
I do not destroy the class explicitely, but I simply expected it to go out of out scope automatically and terminate.
#pragma once
#include <fstream>
using namespace std;
class CLog
{
public:
CLog(wstring filename);
~CLog();
void WriteString(wstring uString);
private:
wofstream m_stream;
wstring m_sPath;
};
#include "log.h";
#include "strhelper.h"
#include <fstream>
#include <iostream>
#include <string>
#include <locale>
#include <codecvt>
wstring m_sText=L"";
wstring m_sPath=L"";
CLog::CLog(wstring uPath)
{
m_sPath=uPath;
}
void CLog::WriteString(wstring uString)
{
m_sText+=uString;
m_sText+=L"\n";
}
CLog::~CLog()
{
if (FileExists(m_sPath))
{
DeleteFile(m_sPath);
}
//open for appending
m_stream.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t,0x10ffff,std::generate_header>));
m_stream.open(m_sPath,fstream::in | fstream::out | fstream::app);
m_stream << m_sText.c_str();
m_stream.close();
}
I am using Clog like this
void foo() {
wstring sLogPath;
sLogPath=GetSpecialFolderDesktop() + L"\\load.log";
CLog *pLog = new CLog(sLogPath);
pLog->WriteString(L"Something);
}
I am using VC2010.
You are instantiating dynamically the CLog. In that case, you need to delete it explicitly.
If you create it on the stack Clog log(sLogPath), the destructor will be called when the object goes out of scope.

Saving functions in a class C++

I am a total noob.
I have created functions for int to string and string to int conversion.
I want to save them so I can use them in any program, so I can call them like #include <iostream>
Do I do this by creating a class ( which then has no private member variables?)
and if I do it as a class how do I use functions without creating objects?
Basically I want to create my own cmath or string sort of thing but I don't even know what to call it to find out how to make it.
If you have just simple functions you can put them in a namespace, which also acts like a container, then put them in a seperate cpp file together and create a .h file which contains the prototypes.
i.E for mymath.h:
#ifndef MYMATH_H
#define MYMATH_H
namespace mymath
{
int dosomething(int y);
}
#endif
and in the mymath.cpp:
#include "mymath.h"
int mymath::dosomething(int y)
{
}
Then, when you want to use it, you include your #include "mymath.h" file and link the cpp to your project.
mystring.hpp
#ifndef MYSTRING_HPP
#define MYSTRING_HPP
#include <string>
namespace n_mystring
{
std::string & IntToString( int Int );
int StringToInt( std::string & String );
}
#endif
mystring.cpp
#include "mystring.hpp"
std::string & n_mystring::IntToString( int Int ) {
//.... implementation
};
int n_mystring::StringToInt( std::string & String ) {
//.... implementation
};
#include <iostream>
class Tools {
public :
void static sneeze ();
};
void Tools::sneeze ()
{
std::cout << "atchoum";
}
int main () {
Tools::sneeze(); // atchoum
}

how to initialize static reference to std::ofstream?

I have a class Cl with public member
static std::ofstream &_rout;
In main file
ofstream out("output.txt");
ofstream& Cl::_rout(out);
But I have a compilation error: illegal definition or redefinition.
How can I correct it?
Try this.
Logger.h
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
class Logger{
public:
static void open( const string & logFile);
static void close();
// write message
static void write( const string & message);
private:
Logger();
ofstream fileStream;
//Logger instance (singleton)
static Logger instance;
};
Logger.cpp
#include "Logger.h"
Logger Logger::instance;
Logger::Logger(){}
void Logger::open( const string& logFile){
instance.fileStream.open(logFile.c_str());
}
void Logger::close(){
instance.fileStream.close();
}
void Logger::write(const string& message){
ostream& stream = instance.fileStream ;
stream << message<< endl;
}
main.cpp
#include "Salida/Logger.h"
int main(){
Logger::open(path);
Logger::write("text");
Logger::close();
return 0;
}
You can only set the reference at the static/global scope
#include<CL.h>
ofstream& Cl::_rout(out);
int main() {
// ...
}
It is not possible to re-set a reference after it was declared (and initialized). You could achieve what you are after by using pointers instead of references:
class Cl {
static std::ofstream* _rout;
};
std::ofstream* CL::_rout = NULL;
int main() {
ofstream out("output.txt");
Cl::_rout = &out;
}
Note that the pointer will be valid only until out goes out of scope. If this is an issue, allocate the memory dynamically:
ofstream* out = new ofstream("output.txt");
Cl::_rout = out;
And don't forget to delete it when you no longer need the object to avoid memory leaks
Well, you could use the following approach:
#include <fstream>
class CI
{
public:
static std::ofstream &_rout;
};
static std::ofstream out("output.txt");
std::ofstream& CI::_rout = out;
int main()
{
}
The problem with this, however, is that the name of the output file is fixed (hard-coded into the program).
I suggest that you use a pointer instead of a reference:
#include <cstddef>
#include <fstream>
class CI
{
public:
static std::ofstream *_rout;
};
std::ofstream* CI::_rout = NULL;
int main()
{
const char *output_file = "output.txt";
std::ofstream out(output_file);
CI::_rout = &out;
}