I'm working on a cryptocurrency exchange simulator that reads data from a CSV file and turns them into objects. I have a class called orderBook which does the reading. One of the class' functions is getKnownProducts, which prints all currencies as strings.
I want to call the function getKnownProducts from another function in the main cpp file to lists all products.
class OrderBook
{
public:
/** Construct, reading a csv file*/
OrderBook(std::string filename);
/** Return vector of all known products in the dataset*/
std::vector<std::string> getKnownProducts();
//some more code...
};
I made an instance in the main file. (The constructor does read the CSV file but the code is omitted because it's irrelevant)
OrderBook orderBook{"20200601.csv"};
And this is the implementation in the cpp file.
std::vector<std::string> OrderBook::getKnownProducts()
{
std::vector<std::string> products;
std::map< std::string, bool> prodMap;
//OrderBookEntry is a class that has a constructor with the data types required to store the data from the csv file.
for(OrderBookEntry& e : orders)
{
prodMap[e.product] = true;
}
// Flatten map to a vector of strings
for(const auto& productStringBoolPair : prodMap)
{
products.push_back(productStringBoolPair.first);
}
return products;
}
Finally, I tried to call getKnownProducts from the following function when I got the typename error. vs code assumes I'm calling the function using the class but I'm doing so using an instance of the class. What should I do to make it clear?
void printProducts()
{
for(std::string const& p : orderBook.getKnownProducts())
{
std::cout << "products: " << p << std::endl;
}
}
A class is like a blueprint, it's there to create instances of that class type.
You can create static functions, which are just normal functions attached to the scope of that class, but any method needs an object of that class to be called:
class A
{
public:
static void classFunction(){}
void method(){}
};
int main()
{
A::classFunction(); //That's ok, because it's a static function
// A::method(); // Not ok, it needs an instance.
A a; // Here we create an instance of class A
a.method(); // That's ok, we have an instance.
}
In your case, OrderBook is a class name, so you can't call a method without an instance.
Related
I am fairly new to C++ and I am still learning to write clean code.
Below are excerpts from the current legacy code I have.
class A {
public:
setDataManager(dm)
{
_dm = dm;
}
void recieveData(data)
{
_dm.processData(data);
}
private:
std::shared_ptr<DataManager> _dm;
};
class DataManager {
public:
void processData(data)
{
DecodeData dd;
dd.Decode(data);
if (decoded data conatains a value XYZ) {
doActionA();
}
}
};
class DecodeData {
public:
void decode(data)
{
//if data contains key 1
// store the value (setters and getters defined)
//if data contains key 2
// store the value.
......
}
};
main()
{
//ConfigManager reads the location type from config file
A a;
std::shared_ptr<DataManager> dm = std::make_shared<DataManager>(...);
a.setDataManager(dm);
//a.recieveData() gets called
}
The Data received is specific for the type of location.
Currently, the legacy code is defined only for one location(NewYork).
Now I have to add another location to the configuration Manager(Australia).
That means I need to add more statements to decode(data) and additional doActions() in processData();
I want to write clean code by separating out the processing for location NY and Australia, as the data received is different for different locations.
I want to have base class, and split out the processing based on location types.
I am unable to conceptualize it. Is it possible?
How do I approach it?
Thank you.
You can create a shared pointer to a derived class and assign it to a shared pointer to a base class. That seems to be the only piece you are missing.
https://godbolt.org/z/Gf7fb1
#include <memory>
class Base
{
public:
virtual int Foo();
};
class Derived:public Base
{
public:
virtual int Foo();
};
int main()
{
std::shared_ptr<Base> ptrBase = std::make_shared<Derived>();
ptrBase->Foo();
}
So, in your case, you just need to create the right type of DataManager with something like
std::make_shared<DataManagerSpecial>;
and pass it in. Then, be sure the DataManager has the correct and flexible API in its base class. DataManagerSpecial obviously needs to derive from DataManager.
hei i have a c++03 class with a simple constructor that take an integer. And a derived class with serialization methods that should take a filename as a constructor, load the integer from it, and then call the first constructor.
class A {
public:
A(int foo);
}
and a derived class:
class XmlableA : public A {
public:
XmlableA(int foo);
XmlableA(string xmlfilename) {
//load foo from xml
// call A::A(foo)
}
}
i tried some different solution but every time i get
no matching function for call to ‘A::A()’
Almost all answers are same, so I would suggest a different solution, which I would prefer personally.
Define a static member function Create as:
class XmlableA : public A {
public:
XmlableA(int foo);
//static member function
static XmlableA Create(string const & xmlfilename)
{
//load foo from xml
int foo = /*load from file*/;
return XmlableA(foo);
}
};
Usage:
XmlableA xmlable = XmlableA::Create(xmlFile);
Initialize it, like so:
XmlableA(int foo) : A(foo) {}
You may also consider:
private:
static int LoadXML(const string& xmlfilename) {
int ret = ...; << load here
return ret;
}
public:
XmlableA(string xmlfilename) : A(LoadXML(xmlfilename)) {
}
In C++ the Base class is constructed BEFORE the Child class, so you will not be able to do this. You could make a Factory that takes a filename and creates an object based on what is in that file.
Example:
class XmltableAFactory {
public:
static XmltableAFactory build(string xmlfilename) {
// read int foo from xmlfilename
return XmltableAFactory(foo);
}
};
And then call it like so:
XmltableA myObj = XmltableAFactory::build(filename);
There are a few things to note.
This means that you will not need the string xmlfilename cosntructor in the XmltableA class because as discussed above, you cannot know foo before the base class's constructor is called.
You can either choose to return from the factory by value or by pointer. The compiler might optimize the return by value because you are creating the object and returning it on the same line. However, return by pointer is usually known to be faster, but you'll have to create a new object and then make sure to delete it when you're done with it.
If you don't want to muck about with memory, take a look at boost's auto_ptr and shared_ptr.
If you want to do something before the call to A::A(int), you end up having to hack, something like
int XmlableA::f(string filename) { /* load foo from xml */; return foo; }
XmlableA(string xmlfilename) : A(f(filename)) {}
OK, so the first one is easy:
XmlableA::XmlableA(int foo) : A(foo)
{
}
The second one requires doing something like
XmlableA(string xmlfilename) : A(fooFromXML(xmlfilename))
{
}
which we can implement as
class XmlableA : public A
{
static int fooFromXML(string filename);
public:
// ...
Note that fooFromXML, which loads the XML file and returns the integer you need, must be static, because when we call it we don't yet have an XmlableA instance to invoke it on.
For multiple arguments (and as a general design), the factory is probably best: if you're wedded to the constructor model and don't care about efficiency, you can do:
class XmlableA : public A
{
static int intFromXML(char const *varname, string const &filename);
public:
XmlableA(string const &xmlfilename)
: A(intFromXML("foo", xmlfilename), intFromXML("bar", xmlfilename))
{
}
if you're concerned about parsing the XML file repeatedly, and don't care about re-entrancy, you can "memoize" xFromXML by having it cache state in a static member.
If your class A does not have a default constructor you have to explicitly call a constructor in the initialization list of your derived class. XmlableA(string fn) : A(readIntegerFromFile(fn)) {}.
However, you should think about "outsourcing" the serialization into a separate class. E.g. what would happen if you have an object of type A and now you want to serialize it? You couldn't because you can only serialize a XmlableA. Furthermore, what would happen if your client decides that he no longer wants a XML serialization but Yaml or some proprietary format? You would have to change all your code.
I want to write a class for some use. I want to call a function (say generate) of this class which will generate two objects of this same class. These two objects will call other function of the class.
Can anyone tell me how to do this?
I want it in C++
Class Example{
public:
generate();
other_func();
}
int main()
{
Example generate();
}
Now this generate function should create two object of Example and will call other_func();
Well, from your description it would sound very easy:
struct Example
{
public:
static void generate() { Example e1, e2; e1.other_fun(); e2.other_fun(); }
void other_fun() { }
};
You can use factory methods to generate objects of specified class. Then the created objects based on the business logic processing can invoke other methods.
The only member functions of a class that can be called without an existing member of a class are static member functions. This is a more in depth topic, please see http://www.cprogramming.com/tutorial/statickeyword.html
So here I create a foo that does what you seem to have asked for and returns the foos:
class foo
{
public:
static void generate()
{
foo Temp1;
foo Temp2;
Temp1.bar();
Temp2.bar();
}
void bar()
{
}
};
edit: I removed the return type, per request
edit: I removed the return type completely, and correctly this time. But now I haven't test compiled the code.
Suppose I have a class Image. At some point in parsing, "Image" is read in at the appropriate time, meaning I want to create an object of class Image.
What I'm considering is mapping these strings to a constructor call to the appropriate class, but I'm not sure how to accomplish this.
I.e.
container.push_back( some_map[stringParsedIn] ); // basic idea
As Stephen pointed out, what you are describing is the Factory pattern (assuming that Image is an abstract base class). However, for its implementation, it might be helpful to associate strings with creation functions as you described instead of a large function consisting of if/else statements. Here's one way to do it (assuming your image subclasses can all be constructed the same way):
typedef Image* create_image_function();
template <class T>
Image* create_image(SomeType arg)
{
return new T(arg);
}
...
map<string, create_image_function*> creators;
creators["Foo"] = &create_image<Foo>;
creators["Bar"] = &create_image<Bar>;
creators["Baz"] = &create_image<Baz>;
shared_ptr<Image> ImageFactory::make_image(const string& str)
{
// checking to see if str exists as a key
// would be nice
return shared_ptr<Image>(creators[str](arg));
}
I am not 100% sure what you are asking, but I'll give it a guess.
You could wrap the constructors in functions:
Image* makeImage(ArgType arg) { return new Image(arg); }
And then you can store function pointers in your map!
map["Image"] = makeImage;
Later to call them!
SuperclassOfImage soup = map["Image"](arg);
Of course the limitation here is that the type signatures of the functions must take the same type argument and must return the same type (an instance of a class that is either Image or a parent of Image).
You can't store function pointers to constructors, but you could store a pointer to a function which returns a newly constructed object, i.e.
Image *createImage() {
return new Image();
}
You could then store a pointer to this function in your map.
std::map<std::string, Image *(*)()> constructorMap;
constructorMap.insert(std::pair<std::string, Image *(*)()>("Image", createImage));
And then call it with
Image *myImage = constructorMap["Image"]();
You're describing a factory function. There are many ways to accomplish this, from registries to simple if/else chains.
Usually your Image class derives from a similar base class to other "parsed in" types. That way, you can add them all to the same container.
Imagine this hierarchy:
class Media {
public:
virtual Save() = 0;
};
class Image : public Media {
public:
Image() { }
virtual Save() { ... }
};
class Sound : public Media {
public:
Sound() { }
virtual Save() { ... }
};
The simplest construct is a factory function:
Media *CreateMedia(const string &type) {
if (type == "Image") {
return new Image;
} else if (type == "Sound") {
return new Sound;
} else {
// handle invalid type error
}
}
Another alternative is to use a registry, instead of CreateMedia you would usually use a macro, a factory/registry and some mechanism to create your subclasses:
// This is some mechanism to create types of Media.
template <typename T>
struct CreatorFunction {
Media *operator() {
return new T;
}
};
// This is the factory that the types will register with.
class Factory {
public:
// singleton access function.
static Factory* Get() {
static Factory* f = new Factory;
return f;
}
// Creates Media of the given type.
Media* Create(const string& name) { return registry_[name](); }
// Records 'name' with the creator function 'func'.
void Add(const string& name, const CreatorFunction &func) {
registry_.insert(name, func);
}
private:
Factory() { } // users can't create factories, they can only use singleton.
hash_map<string, CreatorFunction> registry_;
};
#define REGISTER_MEDIA(type) Factory::Get()->Add(#type, CreatorFunction<type>);
REGISTER_MEDIA(Image); // usually goes with the Image class.
REGISTER_MEDIA(Sound); // usually goes with the Sound class.
int main(int argc, char** argv) {
string parsedIn = "Image";
Factory::Get()->Create(parsedIn);
}
This is a cleaner approach overall, but you may have problems with your linker thinking some symbols are unused and trimming the important registered classes out of your binary. You'll probably want to stick with the if/then chaining until you need something more sophisticated. You usually go for registries once it's infeasible to have a single location where all subtypes are defined.
I have a class that contains some data: class DATA
Now I would to create some functions that uses those data. I can do it easily by writing member functions like DATA::usedata();
Since there are hundreds of functions, I would to keep an order in my code, so I would like to have some "categories" (not sure of the correct name) like:
DATA data;
data.memory.free();
data.memory.allocate();
data.file.import();
data.whatever.foo();
where memory, file and whatever are the "categories" and free, allocate and foo are the functions.
I tried the inheritance way, but I got lost since I can not declare inside DATA a memory or file object, error C2079 occurs: http://msdn.microsoft.com/en-us/library/9ekhdcxs%28VS.80%29.aspx
Since I am not a programmer please don't be too complicated and if you have an easier way I am all ears.
Give your data class some classes of its own, and let those classes refer to the data object that holds them. It sounds like you might have tried to do that already. If you got an error, then you were doing something else wrong.
struct DATA
{
struct DataMemory
{
DATA& data;
DataMemory(DATA& d): data(d) { }
void free();
void allocate();
};
struct DataFile
{
DATA& data;
DataFile(DATA& d): data(d) { }
void import();
};
struct DataWhatever
{
DATA& data;
DataWhatever(DATA& d): data(d) { }
void foo();
};
DataMemory memory;
DataFile file;
DataWhatever whatever;
DATA(): memory(*this), file(*this), whatever(*this) { }
};
Each of the inner classes has a member that's a reference to the containing DATA object. They have constructors to allow that member to get assigned. The DATA class itself also has a constructor to initialize each of its members with a reference to itself.
You can now implement the functions and refer to any of the DATA object's members.
void DATA::DataMemory::free()
{
data.whatever.foo();
}
The inner classes aren't required to be inner classes; they could be standalone top-level classes like DATA if you want, but I think nesting them helps show their interdependence.
The easiest way would be to do the categories just as a naming convention. If you replace the . with _ you don't need any "subobjects" and get:
data.memory_free();
data.memory_allocate();
data.file_import();
This way you basically have the same function names but avoid all the implementation problems of the subobject approach.
If you have a class that has hundreds of member functions, you almost certainly need to break that up into multiple classes. To achieve the type of naming syntax that you're after you could use name spaces to group related classes into "categories."
class DATA
{
public:
class CategoryA_Class
{
friend DATA;
private:
CategoryA_Class() { }
public:
bool GiveMeSomeInt() { return 1; }
};
class CategoryB_Class
{
friend DATA;
private:
CategoryB_Class() { }
public:
bool GiveMeSomeBool() { return true; }
};
public:
CategoryA_Class CategoryA;
CategoryB_Class CategoryB;
};
int _tmain(int argc, _TCHAR* argv[])
{
DATA mydata;
int a = mydata.CategoryA.GiveMeSomeInt();
bool b = mydata.CategoryB.GiveMeSomeBool();
return 0;
}
It is normal to feel confuse when you have so many functions in one class. The trick is to break it all up so that the information is contained in smaller classes that inherits a parent class that has common functions and data to all children.
From what I see you already found a common name for the information. class DATA can be that parent class. Now, you need to break up the information into types of Data. In other words, you will have children classes that will be specialized in something. A quick way to divide the information is to create a diagram of a parent class linked with children classes.
Here is a small example of what you could do:
//parent class
template <class T> class Data
{
T data_; //you could use an array like a std::vector or
//use a stream
public:
//...
void foo();
T getData() const;
};
//child class
template <class T> class Memory
: public Data
{
public:
void free();
void allocate(T data);
//...
};
//child class
template <class T> class File
: public Data
{
public:
T readFile(); //could read the contents of a
//file and save it in data_ (class member from parent class)
void writeFile(); //could write data_
//(class member from parent class) to a file
//...
};
Also, here is documentation if you need help on the concept of inheritance.