initialize a static member with a file - c++

I have a dictionary class , for spell checking . I have an array as the list of words , and I must initialize it with a file that there are words in it .
my problem is that , I need my wordlist variable to be a static variable , cause only one of it is enough for any other extra object created from the dictionary class and it is logical , however there is no need for a second object of the class , but what if we needed more than one object? is there a way?
#ifndef DICTIONARY_H
#define DICTIONARY_H
class Dictionary
{
public:
static const int SIZE = 109582;
Dictionary();
bool lookUp(const char *)const;
private:
void suggestion(const char *)const;
char *wordList[SIZE];
};
#endif
wordlist must be static ...
I only can think of this kind of defining ...
Dictionary::Dictionary()
{
ifstream inputFile("wordsEn.txt", std::ios::in);
if (!inputFile)
{
cerr << "File could not be opened." << endl;
throw;
}
for (int i = 0; i < SIZE && !inputFile.eof(); ++i)
{
wordList[i] = new char[32];
inputFile >> wordList[i];
}
}

There are many ways to solve the programming problem.
Here's my suggestion:
Move the static members out of the class.
class Dictionary
{
public:
Dictionary();
bool lookUp(const char *)const;
private:
void suggestion(const char *)const;
};
In the .cpp file, use:
static const int SIZE = 109582;
static std::vector<std::string> wordList(SIZE);
static int initializeWordList(std::string const& filename)
{
// Do the needul to initialize the wordList.
}
Dictionary::Dictionary()
{
static int init = initializeWordList("wordsEn.txt");
}
This will make sure that the word list is initialized only once, regardless of how may instances of Dictionary you create.

Related

Class 'FileIO' has an illegal zero-sized array; Multiple char strings as member data issue

All I want is to store multiple char arrays as member data in the private field of my FileIO class. For some reason I can have one char array and it works fine, but I soon as I add a second, I get an the error stated in the title.
This code works fine:
class FileIO
{
private:
char accNum[];
public:
FileIO();
~FileIO();
void WriteData(Account*);
void WriteData(Person*);
void ReadData(Account*);
};
This code throws an error:
class FileIO
{
private:
char accNum[];
char persName[];
public:
FileIO();
~FileIO();
void WriteData(Account*);
void WriteData(Person*);
void ReadData(Account*);
};
accNum[] is being used in the ReadData(Account*) function to store one character retrieved from a text file using getline(). Here's the code for that:
void FileIO::ReadData(Account * acc)
{
ifstream accFile("accInfo.txt");
accFile.getline(accNum, 100);
cout << accNum << "\n";
accFile.close();
}
There are more lines in the same text file that I want to store in separate char arrays, but as you can see, I can apparently only have one array as a member variable of the FileIO class. Why is this?
char accNum[]; is a zero sized array and is illegal in C++.
If you are going to be dealing with "strings" then you should scrap using c-style strings and use a std::string. Using a std::string your code would then become
class FileIO
{
private:
std::string accNum;
public:
FileIO();
~FileIO();
void WriteData(Account*);
void WriteData(Person*);
void ReadData(Account*);
};
void FileIO::ReadData(Account * acc)
{
ifstream accFile("accInfo.txt");
getline(accFile, accNum);
cout << accNum << "\n";
accFile.close();
}

still no way to initialize private static field in .h files?

I have Commons.h file that contains "general" structures and classes declarations. Among others it contains such class declaration (only static int nInstrument is important, you can ignore the rest):
class Instrument
{
public:
int Id() {
return _id;
}
int GateId() {
return _gateId;
}
const std::string& const ClassCode() const {
return _classCode;
}
const std::string& const Ticker() const {
return _ticker;
}
Instrument(int gateId_, std::string classCode_, std::string ticker_)
{
_gateId = gateId_;
_classCode = classCode_;
_ticker = ticker_;
_id = nInstrument;
std::cout << "New Instrument created << " << _ticker << " id = " << _id << std::endl;
++nInstrument;
}
private:
static int nInstrument;
int _id;
int _gateId;
std::string _classCode;
std::string _ticker;
};
I need to initialize static int nInstrument; with 0. It's easy If I have Commons.cpp file as answered in this question. But I don't ave Commons.cpp file and I don't want to create it just to put one line int Instrument::nInstrument = 0;
I want to double check that C++11 or future standart still doesn't have such feature? So I have to add cpp just to put one initialization line?
If want want to have a static variable into a header only, you may use the following in your class:
static int& nInstrument() { static int s_i = 0; return s_i; }
The C++11 has this kind of feature, but the most common compiler do not support it (yet). I tested that with XCode and VS2013. I got another solution, based on a question I already asked yesterday.
you have to form the attribute into a method:
class Instrument
{
// your stuff
static int getInstrument()
{
static int nInstrument=1234;
return nInstrument;
}
};
This is header only. You can even extend that, look at the answers at:
How to change a behavior for all instances of a class in a header only class
You can make a workaround using templates (which allow instantiating static members directly in a header file):
class Instrument
{
template<class T>
struct Counter { static int value; };
int _id;
public:
Instrument()
: _id(Counter<int>::value++)
{}
int id() { return _id; }
};
int Test::Counter<int>::value = 1;

a function instead of copy-and-paste programming

I have an object, every member variable in this object has a name which I can acquire it by calling get_name() ,what I want to do is concatenate all the names of the member variables in alphabetical order, then do something. for example:
class CXMLWrapper<class T>
{
public:
CXMLWrapper(const char* p_name) : m_local_name(p_name)
{
}
//skip the get_name(), set_name() and others
private:
string m_local_name;
T m_type_var;
}
class object
{
public:
object() : m_team("team"), m_base("base")
{
}
public:
CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;
...
}
I have to hard-code like this:
object o;
string sign = o.m_base.get_name();
sign += o.m_team.get_name();
I need a function to do this instead of copying and pasting when the object varies. Anyone has an idea?
One way to do this in normal C++, provided all of the members belong to the same class or are derived from some base class will be to use variable number of arguments to a function. An example follows.
#include <stdarg.h>
string concatenateNames(int numMembers, ...)
{
string output;
va_list args;
va_start(args, numMembers);
for(int i = 0; i < numMembers; i++)
{
MemberClass *pMember = va_arg(args, MemberClass*);
output += pMember->get_name();
}
va_end(args);
return output;
}
class Object
{
public:
MemberClass x;
MemberClass y;
MemberClass z;
};
int main()
{
Object o;
string sign = concatenateNames(3, &o.x, &o.y, &o.z);
}
If the types of all the members are different, you can look into variadic templates of C++11x: http://en.wikipedia.org/wiki/Variadic_Templates, but I can't seem to find a way to do otherwise.
If variables which have name have a same type (or these types belongs one hierarchy) you can use map of these vars. Is not good way, but maybe it helps you
Example
class object
{
public:
object() //: m_team("team"), m_base("base")
{
this->vars["m_team"] = CXMLWrapper<string>("team");
//.....
}
public:
map<string, CXMLWrapper<string> > vars;
/*CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;*/
...
}
object o;
string sign;
for(auto& x : o.vars)//i cannot remember syntax of for of map
sign += x.get_name;
PS Sorry for my writing mistakes. English in not my native language.
One method is to have an external library of member names which the CXMLWrapper class updates:-
class BaseXMLWrapper
{
public:
void ListMembers (const char *parent)
{
// find "parent" in m_types
// if found, output members of vector
// else output "type not found"
}
protected:
void RegisterInstance (const char *parent, const char *member)
{
// find 'parent' in m_types
// if not found, create a new vector and add it to m_types
// find 'member' in parent vector
// if not found, add it
}
private:
static std::map <const std::string, std::vector <const std::string> >
m_types;
};
class CXMLWrapper <class T, const char *parent> : BaseXMLWrapper
{
public:
CXMLWrapper(const char* p_name) : m_local_name(p_name)
{
RegisterInstance (parent, p_name);
}
// you could override assignments, copy and move constructors to not call RegisterInstance
//skip the get_name() set_name()
private:
m_local_name;
}
class object
{
public:
object() : m_team("team"), m_base("base")
{
}
public:
CXMLWrapper<string, "object"> m_team;
CXMLWrapper<string, "object"> m_base;
...
};
This does add overhead to the construction of objects, but as it's only a constructor overhead it might not affect overall system performance much.
This looks like a "observe pattern", you just need to keep a single copy in object as a member variable "string name_;", and pass the name_s's reference into CXMLWrapper like this:
class CXMLWrapper<class T>
{
public:
CXMLWrapper(const string &name)
: local_name_(name)
{
}
//skip the get_name() set_name()
private:
const string &local_name_;
}
class object
{
public:
object()
: team_("team"),
base_("base"),
m_team(team_)
, m_base(base_)
{
}
public:
string team_;
string base_;
CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;
}

Initializing C++ const fields after the constructor

I want to create an immutable data structure which, say, can be initialized from a file.
class Image {
public:
const int width,height;
Image(const char *filename) {
MetaData md((readDataFromFile(filename)));
width = md.width(); // Error! width is const
height = md.height(); // Error! height is const
}
};
What I could do to fix the problem is
class Image {
MetaData md;
public:
const int width,height;
Image(const char *filename):
md(readDataFromFile(filename)),
width(md.width()),height(md.height()) {}
};
However
It forces me to save MetaData as a field in my object. Which I don't always want.
Sometimes the logic in the constructor is much more complex than a single read (say, error handling can take a few lines)
So the only solution I thought of is along the lines of
class A {
int stub;
int init(){/* constructor logic goes here */}
A():stub(init)/*now initialize all the const fields you wish
after the constructor ran */{}
};
Is there a better idea? (In Java, you're allowed initializing finals in the constructor).
You could move width and height into one type and move the initialization code into an initialization helper function:
// header:
struct Size {
int width, height;
Size(int w, int h) : width(w), height(h) {}
};
class Image {
const Size size; // public data members are usually discouraged
public:
Image(const char *filename);
};
// implementation:
namespace {
Size init_helper(const char* filename) {
MetaData md((readDataFromFile(filename)));
return Size(md.width(), md.height());
}
}
Image::Image(const char* filename) : size(init_helper(filename)) {}
You can simply use the NamedConstructor idiom here:
class Image
{
public:
static Image FromFile(char const* fileName)
{
MetaData md(filename);
return Image(md.height(), md.width());
}
private:
Image(int h, int w): mHeight(h), mWidth(w) {}
int const mHeight, mWidth;
};
One of the main advantage of Named Constructors is their obviousness: the name indicates you are building your object from a file. Of course it's slightly more verbose:
Image i = Image::FromFile("foo.png");
But that never troubled me.
If it was C++0x, I would recommend this (delegating constructors):
class Image
{
public:
const int width, height;
Image(const char* filename) : Image(readDataFromFile(filename)) { }
Image(const MetaData& md) : width(md.width()), height(md.height()) { }
};
You should add inline getters for the width and height instead of public const member variables. The compiler will make this solution as fast as the original try.
class Image {
public:
Image(const char *filename){ // No change here
MetaData md((readDataFromFile(filename)));
width = md.width();
height = md.height();
}
int GetWidth() const { return width; }
int GetHeight() const { return height; }
private:
int width,height;
};
P.S.: I used to write private things at the end because they are less important for the user of the class.
First, you should understand the constructor body is just for running code to complete initializing your object as a whole; the members must be completely initialized before the body is entered.
Ergo, all members are initialized in an (implicit unless made explicit) initialization list. Clearly, const variables must be initialized in the list because once you enter the body, they are already suppose to be initialized; you'd simply be trying to assign them.
Generally, you don't have const members. If you want those members to be immutable, just don't give any public access to them that could change them. (Also, having const members make your class non-assignable; typically unnecessarily.) Going this route easily fixes your problem, as you'd just assign them values in the body of the constructor like you wish.
A method to do what you want while maintaining const could be:
class ImageBase
{
public:
const int width, height;
protected:
ImageBase(const MetaData& md) :
width(md.width()),
height(md.height())
{}
// not meant to be public to users of Image
~ImageBase(void) {}
};
class Image : public ImageBase
{
public:
Image(const char* filename) : // v temporary!
ImageBase(MetaData(readDataFromFile(filename)))
{}
};
I don't think this route is worth it.
You could cast away the constness in the constructor:
class Image {
public:
const int width,height;
Image(const char *filename) : width(0), height(0) {
MetaData md(readDataFromFile(filename));
int* widthModifier = const_cast<int*>(&width);
int* heightModifier = const_cast<int*>(&height);
cout << "Initial width " << width << "\n";
cout << "Initial height " << height << "\n";
*widthModifier = md.GetWidth();
*heightModifier = md.GetHeight();
cout << "After const to the cleaners " << width << "\n";
cout << "After const to the cleaners " << height << "\n";
}
};
That would achieve what you want to do but I must say I personally would stay away from that because it causes undefined behavior according to the standard (excerpt from cppreference)
const_cast makes it possible to form a reference or pointer to
non-const type that is actually referring to a const object ...
Modifying a const object through a non-const
access path ... results in undefined behavior.
I would fear any public data members(at least in regarding your particular example). I would go with Georg's approach or make the data private and provide only the getter.
How about passing MetaData as an argument to the constructor. This gives a lot of benefits:
a) The constructor interface makes it clear about the dependency on MetaData.
b) It facilitates testing of the Image class with different types of MetaData (subclasses)
So, I would probably suggest similar to follows:
struct MD{
int f(){return 0;}
};
struct A{
A(MD &r) : m(r.f()){}
int const m;
};
int main(){}
I'd use a static method:
class Image {
public:
static Image* createFromFile( const std::string& filename ) {
//read height, width...
return new Image( width, height );
}
//ctor etc...
}
class A
{
public:
int weight,height;
public:
A():weight(0),height(0)
{
}
A(const int& weight1,const int& height1):weight(weight1),height(height1)
{
cout<<"Inside"<<"\n";
}
};
static A obj_1;
class Test
{
const int height,weight;
public:
Test(A& obj = obj_1):height(obj.height),weight(obj.weight)
{
}
int getWeight()
{
return weight;
}
int getHeight()
{
return height;
}
};
int main()
{
Test obj;
cout<<obj.getWeight()<<"\n";
cout<<obj.getHeight()<<"\n";
A obj1(1,2);
Test obj2(obj1);
cout<<obj2.getWeight()<<"\n";
cout<<obj2.getHeight()<<"\n";
return 0;
}
As far my understanding i think this mechanism will work.
This is one of my least favorite aspects of C++ when compared to Java. I'll use an example I was working on when I needed to solve this problem.
What follows is the equivalent of a readObject method. It deserializes a Video key from a provided file path.
#include <fstream>
#include <sstream>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
using namespace std;
using namespace boost::filesystem;
using namespace boost::archive;
class VideoKey
{
private:
const string source;
const double fps;
const double keyFPS;
const int numFrames;
const int width;
const int height;
const size_t numKeyFrames;
//Add a private constructor that takes in all the fields
VideoKey(const string& source,
const double fps,
const double keyFPS,
const int numFrames,
const int width,
const int height,
const size_t numKeyFrames)
//Use an initializer list here
: source(source), fps(fps), keyFPS(keyFPS), numFrames(numFrames), width(width), height(height), numKeyFrames(numKeyFrames)
{
//Nothing inside this constructor
}
public:
//Then create a public static initializer method that takes in
//the source from which all the fields are derived
//It will extract all the fields and feed them to the private constructor
//It will then return the constructed object
//None of your fields are exposed and they are all const.
const static VideoKey create(const path& signaturePath)
{
const path keyPath = getKeyPath(signaturePath);
ifstream inputStream;
inputStream.open(keyPath.c_str(), ios::binary | ios::in);
if (!inputStream.is_open())
{
stringstream errorStream;
errorStream << "Unable to open video key for reading: " << keyPath;
throw exception(errorStream.str().c_str());
}
string source;
double fps;
double keyFPS;
int numFrames;
int width;
int height;
size_t numKeyFrames;
{
binary_iarchive inputArchive(inputStream);
inputArchive & source;
inputArchive & fps;
inputArchive & keyFPS;
inputArchive & numFrames;
inputArchive & width;
inputArchive & height;
inputArchive & numKeyFrames;
}
inputStream.close();
//Finally, call your private constructor and return
return VideoKey(source, fps, keyFPS, numFrames, width, height, numKeyFrames);
}

static public member function ( C++ )

I need to count the times my public member function creates new data in a loop.
Each time data is read it is saved into a private member varaible. Nothing is overwritten.
// my classType.h
const int ImpliedIndex = 1000;
class classType
{
private:
char privateMember[ImpliedIndex];
char privateMember2[ImpliedIndex];
public:
static void myMemberCounter;
void printMyInformation():
void mySupplier(const char[] );
...
};
//classType.cpp
int globalCounter = 0;
void classType::printMyInformation()
{
...
cout << privateMember << endl;
cout << globalCounter++ << endl;
}
void classType::mySupplier( const char buff[] )
{
strcpy( privateMember, buff );
}
// The main should clear things up a bit.
// main.cpp
int main()
{
while ( !inFile.eof() )
{
for ( int x = 0; x < 20; x++ )
{
// do file I/O here
// save each line of file into an temp array
// supply temp array with a routine defined in myClass
// re-use temp array until we run out of file
}
}
//close file
I need to change my 20 to a variable. Notice that in classType I used globalCounter to retrieve the number of types.
What I wanted to do is, globalCounter = memberCounter;
But I have to re-declare both of these varaibles, and I can't use myClass[ImpliedIndex].memberCounter with the assignment operator (=) or the binary insertion operator(<<).
This line:
static void myMemberCounter;
Should generate a compile-time error. It looks like a variable, but has type void, which doesn't make sense.
If you want a static ("class variable") counter, you should use a type like int. Then it would be easy for the class to use that counter to count the number of instances, by just incrementing the counter in the constructor. The count can be read by the outside world by adding a public class function to return it.