shared_ptr to derived class - c++

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.

Related

Namespace Functions within Class alternatives?

I'd like to be able to group similar functions in a class into a group so I don't need to append each name with what it's about.
I've seen this question which says that you can't have namespaces within classes. I've also seen this question which proposes using strongly typed enums. The problem here though, is that I'm not sure whether or not these enums can actually accomodate functions?
The problem contextualised:
class Semaphore
{
public:
void Set(bool State){Semaphore = State;}
bool Get(){return Semaphore;}
void Wait()
{
while (Semaphore)
{
//Wait until the node becomes available.
}
return;
}
private:
bool Semaphore = 0; //Don't operate on the same target simultaneously.
};
class Node : Semaphore
{
public:
unsigned long IP = 0; //IP should be stored in network order.
bool IsNeighbour = 0; //Single hop.
std::vector<int> OpenPorts;
//Rest of code...
};
Currently, NodeClass.Get() is how I can get the semaphore. However this introduces confusion as to what Get() actually gets. I'd like to have something akin to NodeClass.Semaphore::Get(). Otherwise I'd have to have the functions as SemaphoreSet(), SemaphoreGet(), and SemaphoreWait(), which isn't too well organised or nice looking.
I had thought of just having the Semaphore class on it's own, and instantiating it within the other classes, but if I could stick with the inheritance approach, that would be nicer.
So essentially, is it possible to access inherited methods like InheritedClass.Group::Function()?
If you really want to do this, you could force the user to call with the base class name by deleteing the member function in the subclass:
class Base {
public:
void Set(bool) { }
};
class Derived : public Base {
public:
void Set(bool) = delete;
};
int main() {
Derived d;
// d.Set(true); // compiler error
d.Base::Set(true);
}
However, if the semantics of calling Set on the subclass are significantly different than what you'd expect them to be when calling Set on the base class, you should probably use a data member and name a member function accordingly as you've described:
class Base {
public:
void Set(bool) { }
};
class Derived {
public:
void SetBase(bool b) {
b_.Set(b);
}
private:
Base b_;
};
int main() {
Derived d;
d.SetBase(true);
}

Creating C++ classes using an array of class definitions

I am writing a program that reads documents from a data base and turns the contents into C++ class instantiations. In each document there is a "type" field that I am mapping to a particular C++ class. Basically I read the document, construct an object of the corresponding class, and fill out the fields of the class object. I have maybe 10-15 different types of classes because the types of data in each document may be different, although some of the types are common. The common types of data are reflected in base/derived class definitions. Right now I have a switch statement with case statements corresponding to the different types of objects and in each case statement I create the right kind of object and then fill it in. It is a little messy though.
I was wondering if there is a means to place the various class definitions in an array so that I can mostly get rid of the switch statement. My ideal code would look like:
auto * obj = new arrayOfClassDefinitions[typeofClassIndex]
where arrayOfClassDefinitions contains the names of a set of classes. The obj pointer would then point to a new instantiation of the desired class.
I recall I could do things like this in Python but I am not sure about C++.
any ideas??
If you can organize all your classes into one hierarchical tree, you could use Abstract factory pattern to get similar result. This is example:
#include <map>
#include <memory>
class IBaseClass {
public:
virtual ~IBaseClass(){}
};
class A : public IBaseClass {
public:
// ....
};
class B : public IBaseClass {
public:
// ....
};
class C : public IBaseClass {
public:
// ....
};
class IFactory {
public:
virtual ~IFactory(){}
virtual IBaseClass* create() = 0;
};
template <class T>
class SimpleFactory :
public IFactory {
public:
IBaseClass* create() override {
return new T();
}
};
template <typename T>
std::shared_ptr<IFactory> make_factory() {
return std::make_shared<SimpleFactory<T> >();
}
int main(int, char**)
{
std::map<int, std::shared_ptr<IFactory>> factories = {
{1, make_factory<A>()},
{2, make_factory<B>()},
{3, make_factory<C>()}
};
// ....
int type_index = 1;
auto obj = factories[type_index]->create();
// ...
// don't forget to delete
delete obj;
return 0;
}

Can you set pointer to derived class after you set some values in the base class?

I am new to c++ (I am using visual studio 2013) and I started experimenting with classes and inheritance. So I came up with a question which I can not find any anwser. Lets say we have this class:
#include <iostream>
using namespace std;
class base{
protected:
int var;
public:
void setvalue(int);
virtual void print();
};
class first:public base{
public:
void print();
};
class second: public base{
public:
void print();
};
Is there a way I can declare in my main() a pointer to base, set the value and after that choose if it is a first or second class? Ex:
int main(){
base *ptr = new base;
ptr->setvalue(1);
/* Here I choose if base is pointing to First or Second class*/
ptr->print(); // use the correct member, based on which class I choosed
return 0;}
Is this somehow possible? (As I said I am new to c++ so in case you have any questions, feel free to ask!)
Thanks!
Since it's not possible, the only thing that comes to mind is that you solve your problem in another way, perhaps using some well common design pattern.
In this case, given the little information you gave, Factory pattern seems appropriate.
#include <iostream>
using namespace std;
class base {
protected:
int var;
public:
void setvalue(int);
virtual void print();
static base* makeObject(int);
};
class first : public base {
public:
void print();
};
class second : public base {
public:
void print();
};
base* base::makeObject(int param) {
base* ret = NULL;
if(/* some condition based on params */) {
ret = new first();
ret->setvalue(0);
} else if(/* some other condition */) {
ret = new second();
ret->setvalue(1);
}
return ret;
}
int main() {
base *ptr = base::makeObject(...);
base->print(); // use the correct member, based on which class I choosed
return 0;
}
The type of an object is fixed at construction and can never be changed. So the direct answer to your question is "no".
But within that framework you have a lot of power. For example, you could separate your three classes out into four: three that do just do printing (BasePrinter, DerivedPrinter1, DerivedPrinter2) and other that just holds the value and doesn't have any virtual methods. Your BasePrinter class could get passed a ValueHolder object (by const reference) every time you call the print() method. Alternatively, each ValueHolder could have a pointer to BasePrinter object and pass in all the necessary data each time, with a little (non-virtual) print() method to do all this forwarding.
Not directly. When you create an object, you need to specify its full type so that C++ knows how to correctly lay out memory for you.
If you actually need to change it later, you can always create a new class (of the correct derived type) and use the original base class to initialize it, then delete the original. This might be slightly slower than the method you were proposing (depending on the final complexity of the class), but it would get the job done.
Since you are using inheritance , it is best practice to define virtual destructor in your base class. It will take care proper clean up when you define complicated class.
int main(){
base *ptr = new base;
base->setvalue(1);
/* Here I choose if base is pointing to First or Second class*/
base->print(); // use the correct member, based on which class I choosed
return 0;}
What you are trying to do is not possible. You have to change your program as follows to avoid compilation error.
base *ptr = new base;
ptr->setvalue(1);
ptr->print();
delete ptr;
return 0;
Because you base pointer ptr always have the dynamic type of class base. this code always invoke base::print function
If you define ptr as follows, you can utilize the polymorphism.
base * ptr = new first;
ptr->setvalue(1);
ptr-> print()
delete ptr
Here ptr has a dynamic type of class first and it will call function first::print()
You have to choose type at the creation of the object:
int main()
{
base *ptr = new first; // here.
ptr->setvalue(1);
ptr->print(); // use first::print.
delete ptr;
}

What design pattern should I use to avoid dummy code here?

I have a base class -
class content
{
private:
int m_data;
public:
int getdbhandle() { return m_sql_db; }
void setData(int data) { m_data = data; }
virtual int getterrestrialServices { qDebug()"This is a dummy interface"; }
};
class telecontent: public content
{
virtual int getterrestrialServices { qDebug()" Real implementation here"; }
};
Now, the class content is instantiated as telecontent, when the product type is tele.
However, when the product type is generic - the dummy interface prints keep coming.
How can I avoid so? Is there any design pattern that forces the base class not to implement the dummy function? I want an efficient way so that only derived class has method. I don't want the base class to have that method. But, I can't modify the caller - code- so that the method is not called. I want the best way to strategically design such that the dummy interface can be avoided.
is there any design pattern that forces the base class not to
implement the dummy function?
Pure virtual allows this:
class content
{
private:
int m_data;
public:
virtual ~content() { }
int getdbhandle() { return m_sql_db; }
void setData(int data) { m_data = data; }
virtual int getterrestrialServices() = 0; // pure virtual
};
This means no one can create instances of content (will cause a compiler error), and so when some one inherits from content they must provide an implementation of getterrestrialServices() (else again, they'll get a compiler error).
What you need is pure virtual like so:
virtual int getterrestrialServices() = 0;
It will force every class the inherits content to implement it and you wont be able to create a content class, only classes the inherit from it so you wont have the dummy prints.

Problem about C++ class (inheritance, variables scope and functions)

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.