Generic Get and Set as interface
-
Hi all, I want to have an interface for setting and getting the different value from/to com dll. The value can be of any datatype, i,e it support int, char, long, short, string. Can any one suggest how to handle this. I know we cant have virtual template function or interface as a template. Any idea is highly appreciated. Thanks in advance. regards, Durga
-
Hi all, I want to have an interface for setting and getting the different value from/to com dll. The value can be of any datatype, i,e it support int, char, long, short, string. Can any one suggest how to handle this. I know we cant have virtual template function or interface as a template. Any idea is highly appreciated. Thanks in advance. regards, Durga
-
Hi all, I want to have an interface for setting and getting the different value from/to com dll. The value can be of any datatype, i,e it support int, char, long, short, string. Can any one suggest how to handle this. I know we cant have virtual template function or interface as a template. Any idea is highly appreciated. Thanks in advance. regards, Durga
One generic solution that might be suitable has already been posted by CPallini. Another one more C++ish solution could be something like this: Define a base class for your different types:
class CValue
{
};Derive a class for all types you support:
class CStringValue : public CValue
{
public:
// CStringValue specific methods like void SetValue(const std::string&) and
// const std::string& GetValue();
private:
std::string m_Value;
};class CIntValue : public CValue
{
public:
// CIntValue specific methods like void SetValue(int) and
// int GetValue();
private:
int m_Value;
};The advantage of this solution that your data type can be anything, it can contain an int array, or one of your own classes if you want and not just 'primitives'. The derived class itself can be a type put together by compositing other types... Your interface methods should look like the following:
void SetValue(CValue* val);
CValue* GetValue();We reached the point where we want to use the actual value but inside
SetValue()
all we have is aCValue*
that is useless in its current form so we put in some useful virtual methods in this base class. First I want to be able to decide the exact type of the value. For this reason I usually use one or both of the following methods: 1. introducing an enum that contains a member for each supported possible datatype and you can query it from the base class. 2. virtual downcast methods in the base class.class CStringValue;
class CIntValue;class CValue
{
public:
enum EType
{
EType_String,
EType_Int,
};
virtual Etype GetType() = 0;// Downcast methods, not the most beautiful OO solution of the world but sometimes // in a fixed size class hierarchy like this it is acceptable and comfortable, and // more beautiful than using for example C++'s dynamic\_cast. If quite comfortable // to say for example "if (CStringValue\* sv = val->AsStringValue())" // override this only in CStringValue and put "return this;" into the method body. virtual CStringValue\* AsStringValue() { return NULL; } // override this only in CIntValue and put "return this;" into the method body. virtual CIntValue\* AsIntValue() { return NULL; }
};
Note that both the type enum and downcast methods are against the dynamic extensibility of the class hierarchy from outside world, ot
-
One generic solution that might be suitable has already been posted by CPallini. Another one more C++ish solution could be something like this: Define a base class for your different types:
class CValue
{
};Derive a class for all types you support:
class CStringValue : public CValue
{
public:
// CStringValue specific methods like void SetValue(const std::string&) and
// const std::string& GetValue();
private:
std::string m_Value;
};class CIntValue : public CValue
{
public:
// CIntValue specific methods like void SetValue(int) and
// int GetValue();
private:
int m_Value;
};The advantage of this solution that your data type can be anything, it can contain an int array, or one of your own classes if you want and not just 'primitives'. The derived class itself can be a type put together by compositing other types... Your interface methods should look like the following:
void SetValue(CValue* val);
CValue* GetValue();We reached the point where we want to use the actual value but inside
SetValue()
all we have is aCValue*
that is useless in its current form so we put in some useful virtual methods in this base class. First I want to be able to decide the exact type of the value. For this reason I usually use one or both of the following methods: 1. introducing an enum that contains a member for each supported possible datatype and you can query it from the base class. 2. virtual downcast methods in the base class.class CStringValue;
class CIntValue;class CValue
{
public:
enum EType
{
EType_String,
EType_Int,
};
virtual Etype GetType() = 0;// Downcast methods, not the most beautiful OO solution of the world but sometimes // in a fixed size class hierarchy like this it is acceptable and comfortable, and // more beautiful than using for example C++'s dynamic\_cast. If quite comfortable // to say for example "if (CStringValue\* sv = val->AsStringValue())" // override this only in CStringValue and put "return this;" into the method body. virtual CStringValue\* AsStringValue() { return NULL; } // override this only in CIntValue and put "return this;" into the method body. virtual CIntValue\* AsIntValue() { return NULL; }
};
Note that both the type enum and downcast methods are against the dynamic extensibility of the class hierarchy from outside world, ot
Thanks pal. Thanks for ur input. I will try using the first method.
-
Thanks pal. Thanks for ur input. I will try using the first method.
You are welcome! Depending on the complexity and the requirements of your project my solution can be a heavy over-engineering to solve a very small problem. You have to draw the line yourself! Good luck!
-
You are welcome! Depending on the complexity and the requirements of your project my solution can be a heavy over-engineering to solve a very small problem. You have to draw the line yourself! Good luck!
Hi pasztorpisti, I have one doubt. I can go with the enumerator alone , instead of having the downcast method? Can you please explain me how it has to be in implementation class. Thanks in advance.
-
Hi pasztorpisti, I have one doubt. I can go with the enumerator alone , instead of having the downcast method? Can you please explain me how it has to be in implementation class. Thanks in advance.
I don't exactly know the problem you wanna solve and don't know what part is unclear for you. If an enum + GetType() is enough for you then you can omit the downcast methods but either way you choose you will have to downcast the object somehow so without downcast methods you will have to use C++ static cast. As I described in some situations you might need neither the enum nor the downcast, for example if a virtual method like ToString() can do the job.
-
I don't exactly know the problem you wanna solve and don't know what part is unclear for you. If an enum + GetType() is enough for you then you can omit the downcast methods but either way you choose you will have to downcast the object somehow so without downcast methods you will have to use C++ static cast. As I described in some situations you might need neither the enum nor the downcast, for example if a virtual method like ToString() can do the job.
HI pasztporpist As per your input i have done the code
// App_Datatype.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include <tchar.h>
#include <stdio.h>class CStringValue;
class CValue
{
public:enum EType { EType\_String, EType\_Int, }; virtual EType getDataType() = 0; virtual CStringValue\* AsStringValue() { return NULL; }
};
class CStringValue : public CValue
{
private:
std::string m_strValue;public:
void set(const std::string &strVal) { m\_strValue = strVal; } std::string get() { return m\_strValue; } CStringValue\* AsStringValue() { return this; } EType getDataType() { return CValue::EType\_String; }
};
void print(CValue *pVal)
{
if(pVal->getDataType() == CValue::EType_String)
{
CStringValue *val = pVal->AsStringValue();
std::cout<<val->get().c_str();
}
}int _tmain(int argc, _TCHAR* argv[])
{CStringValue \*val = new CStringValue(); val->set("Hai"); print(val); return 0;
}
Is it correct? If not tell me where i did a mistake
-
HI pasztporpist As per your input i have done the code
// App_Datatype.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include <tchar.h>
#include <stdio.h>class CStringValue;
class CValue
{
public:enum EType { EType\_String, EType\_Int, }; virtual EType getDataType() = 0; virtual CStringValue\* AsStringValue() { return NULL; }
};
class CStringValue : public CValue
{
private:
std::string m_strValue;public:
void set(const std::string &strVal) { m\_strValue = strVal; } std::string get() { return m\_strValue; } CStringValue\* AsStringValue() { return this; } EType getDataType() { return CValue::EType\_String; }
};
void print(CValue *pVal)
{
if(pVal->getDataType() == CValue::EType_String)
{
CStringValue *val = pVal->AsStringValue();
std::cout<<val->get().c_str();
}
}int _tmain(int argc, _TCHAR* argv[])
{CStringValue \*val = new CStringValue(); val->set("Hai"); print(val); return 0;
}
Is it correct? If not tell me where i did a mistake
Instead of
std::string get() { return m\_strValue; }
I would write this:
<pre lang="c++">
const std::string& get() const
{
return m_strValue;
}
</pre>getDataType() can also be a const method. In you example (with the print function) I would rather use the
virtual ToString()
method instead of a type enum or casting.