So, let's say I have a few functions to deal with opening/closing of files.
Is it better to make a class with all these function declared statically or simply put the "public" function in the header file of namespace "file", and put the rest "implementation details" in the .cc file?
Below are the code samples.
It's a bit long for the namespace one, as I want to make it as clear as possible.
THANKS!!
the class implementation
Header:
#ifndef FILE_H
#define FILE_H
#include <iostream>
#include <fstream>
include "common.h"
enum Errorcode {
FILE_CANNOT_OPEN,
FILE_CANNOT_CLOSE
};
class file {
public:
static common::Lines toLines(std::string filename);
private:
static void err(Errorcode e, std::string msg);
static void toLines(std::ifstream &ifs, common::Lines &lines);
};
#endif
.cc file:
/*just the implementation details of above class.*/
the namespace implementation
Header:
#ifndef FILE_H
#define FILE_H
#include <iostream>
#include <fstream>
#include "common.h"
namespace file {
common::Lines toLines(std::string filename);
}
#endif
.cc file:
namespace file {
enum Errorcode {
FILE_CANNOT_OPEN,
FILE_CANNOT_CLOSE
};
void err(Errorcode e, std::string msg);
void toLines(std::ifstream& ifs, common::Lines &lines);
common::Lines toLines(std::string filename)
{
std::vector<std::string> lines;
try {
std::ifstream ifs(filename.c_str());
if (ifs.fail()) throw FILE_CANNOT_OPEN;
toLines(ifs, lines);
ifs.close();
if (ifs.fail()) throw FILE_CANNOT_CLOSE;
}
catch (Errorcode e) {
err(e, filename);
}
return lines;
}
void err(Errorcode e, std::string msg)
{
switch (e) {
default:
std::cerr << "Unknown error.\n";
break;
case FILE_CANNOT_OPEN:
std::cerr << "file \"" << msg
<< "\" could not be opened.\n";
break;
case FILE_CANNOT_CLOSE:
std::cerr << "file \"" << msg
<< "\" could not be closed.\n";
break;
}
std::exit(-1);
}
void toLines(std::ifstream& ifs, common::Lines &lines)
{
std::string line;
while(std::getline(ifs, line)) {
lines.push_back(line);
}
ifs.clear(); // clear error bit set by getline()
}
}
Superficially, static class functions and namespaced functions are almost identical, and indeed classes were used in the early days before namespace support became widespread.
Nowadays, you should do what most expresses the logical structure (i.e. the mental model) of your program. If you are grouping related functions, it's a namespace.
However, the technical differences in a nutshell is that namespaces participate in argument-dependent lookup (ADL), while class member functions don't, but classes can be turned into templates and specialized. If any of those semantic differences is important to you, then that consideration may help you make the right choice.
There's a simple question that covers most situations: If you made it a class, would an instance of that class make sense and accomplish something useful?
If an instance is useful, then you want a class. Otherwise, a namespace is probably a better choice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With