|
You may use a VARIANT[^] data type or a similar mechanism.
Veni, vidi, vici.
|
|
|
|
|
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:
private:
std::string m_Value;
};
class CIntValue : public CValue
{
public:
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 a CValue* 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;
virtual CStringValue* AsStringValue() { return NULL; }
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, other libraries. In some cases this isn't a problem at all, it depends on the actual problem. You might omit this whole enum + downcast method thingy as it is. You might be OK with a few other kind of virtual methods that follow:
You can put in for example some kind of serialization/deserialization methods. One often used handy serialization format is the string!
class CValue
{
public:
virtual std::string ToString() const = 0;
virtual bool SetFromString(const std::string& s) = 0;
virtual void SaveToXml(XmlElement* node) = 0;
virtual bool LoadFromXml(XmlElement* node) = 0;
};
EDIT: In case of fixed type hierarchy the visitor pattern might come handly depending on the kind of the problem.
class CValueVisitor;
class CValue
{
public:
virtual void accept(CValueVisitor* visitor);
};
class CValueVisitor
{
public:
virtual void visit(CStringValue* v) = 0;
virtual void visit(CIntValue* v) = 0;
};
If you use visitor then you can implement even the aformentioned serialization methods as visitors. Whether to use virtual methods in your base class, or to use visitor instances depends on your actual problem.
modified 30-Sep-12 11:39am.
|
|
|
|
|
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!
|
|
|
|
|
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.
|
|
|
|
|
HI pasztporpist
As per your input i have done the code
#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.
|
|
|
|
|
Hi coders! I'm new here and I would like to ask if someone knows how to use CR in win32 application in VS2010.
I've tried looking it up in the web but all i can see are CR in MFC something like that.
I have no experience in using CR. I'm trying to learn it.
Hoping for a quick response.
|
|
|
|
|
This[^] would be a good place to start.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Latest version supporting COM interface is CR XI R2, from CR 2008 version there is only .NET interface.
CR XI R2 is not free, you can download from SAP-
|
|
|
|
|
HI.
I have been using 2006 and have not upgraded through the years. All works. Now, I installed VC2008 and find that the old code has many compiler errors. I am not sure where these come from.
One is ex:
for (int x = 0; x< 100;x++)
....
for (x = 0; x<5;x++)....
THis will nor work anymore... It seems I need to declare the X outside the for loop.
The other is :
Error 2440: 'static cast' cannot convert from 'void (thiscall CMyView::*)(WPARAM, LPARAM)' to '(LRESULT (thiscall CWnd::*)(WPARAM, LPARAM)'
Not sure what this one is. Never had any of these problems before.
Also, just curious if maybe I should just go to 2011 version versus 2008? Any comments?
Appreciate any help or advise.
Thanks.
Stan the man
|
|
|
|
|
In your first statement above you declare x to be an integer, however it only exists within the for block, so (I assume, since you did not show all your code) when you get to the second statement, x is unknown. The C2440 message is described here[^].
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
The problem is that it works in the old code. The declaration for x is valid through the function that the second for is in. So it never was a problem before.
|
|
|
|
|
Things change, and compilers enforce standards more rigidly.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
It was not a problem before, because the compiler did things that were not standard. But starting with Visual Studio 2005, the scope of the variables does not exceed the block they are defined in. And that applies to for loops too. So you either declare the index variable before the first for loop, or re-declare it in each for statement.
As for the other problem, it's also an error with the old compiler. Your actual handler should return LRESULT, not void. So change the function to the requested signature (take a WPARAM and LPARAM and return LRESULT) and everything will be OK.
BTW, there is no such thing as VS2006. There is VS2002, VS2003, VS2005 and VS2008.
|
|
|
|
|
Stan the man wrote: for (int x = 0; x< 100;x++)
....
for (x = 0; x<5;x++)....
THis will nor work anymore... It seems I need to declare the X outside the for loop.
This because the VC compiler was not compliant with the C++ standard. See this page[^] for a reason why.
That eventually changed and VC is now compliant.
Stan the man wrote: Error 2440: 'static cast' cannot convert from 'void (thiscall CMyView::*)(WPARAM, LPARAM)' to '(LRESULT (thiscall CWnd::*)(WPARAM, LPARAM)'
Not sure what this one is. Never had any of these problems before.
This is a change in the Microsoft's MFC library (see for instance here[^]).
Veni, vidi, vici.
|
|
|
|
|
Thank everyone for their input. Will go through and properly get everything done. Appreciate the help.
|
|
|
|
|
You are welcome.
Veni, vidi, vici.
|
|
|
|
|
Stan the man wrote: I have been using 2006
Just for my own sanity you are actually referring to VC6 right?
There is no such thing as "VC2006" and the compilers around 2006 such as Visual Studio 2005 were compliant. But Visual Studio C++ 6, known as VC6, was released in 1998 and was not compliant.
|
|
|
|
|
I use the CImage::Load() to load a png file,
and then use SetBitmap() to set this image to Picture Control.
I had define a CStatic member and use DDX_Control to bind this CStatic object to Picture Control. But when CDialog startup, no image shows.
There is a similiar issule about Picture Control. I use the Picture Control to display different button images. When mouse in different area of Picture Control, this control wil display a different image,
I had a initialized operator for this Picture Control, but why only after I use mouse to move in the Picture Control, then this image will show. I do not know any other code needed to written. After SubClassDlgItem().
modified 4-Oct-12 11:38am.
|
|
|
|
|
Code snippet?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|
I'll hazard a guess, maybe this link[^] might help.
|
|
|
|
|
I resolved this problem. Because the CImage is a temperory object.
After change this CImage object to class member, it is OK.
|
|
|
|
|
Hi community,
i have a funktion to count files in a directory and its subdirectory, but how to count a ADS files, alternate da ta stream?
How to pas a path to FindFile() and FindNextFile() ??
I try to make a path from a visible file like:
"C:\visible.txt" to "C:\visible.txt:*.*" but this is not correct.
Does any one knows how to do this?
Thanks in advance
bosfan
|
|
|
|