|
yeti11 wrote: Can you please tell me why? Pointer is a pointer however you turn it... sure if it is object i
understand the reason, but the question is what is the problem if i use it as pointer? Or rather
the question is understanding...
Sure a pointer is a pointer but the object it points to is not altered by casting the pointer. Consider the following:
#include <iostream>
class CClass1
{
public:
CClass1() : m_Data(0) {}
int m_Data;
};
class CClass2
{
public:
CClass2() : m_pData("Hello") {}
const char* m_pData;
};
void main()
{
using namespace std;
CClass2 c2;
CClass1 *pOne = reinterpret_cast<CClass1*>(&c2);
cout << pOne->m_Data << endl;
}
This program will not behave as expected. The cast from CClass2* to CClass1* does not change the CClass2 into a CClass1 ; it just changes the type of the pointer. So the compiler thinks that pOne points to an object of type CClass1 but it actually points to a CClass2 instance.
Steve
|
|
|
|
|
It's not that simple. The following program while perverse compiles and runs just fine and works as expected:
#include <iostream>
#include <vector>
class CBase
{
public:
virtual void Print() { std::cout << "CBase" << std::endl; }
};
class CDerived : public CBase
{
public:
virtual void Print() { std::cout << "CDerived" << std::endl; }
};
int main(int argc, char* argv[])
{
typedef std::vector<CBase*> BVec_t;
typedef std::vector<CDerived*> DVec_t;
DVec_t dvec;
dvec.push_back(new CDerived);
BVec_t &bvec = *reinterpret_cast<BVec_t*>(&dvec);
CBase *pBase = bvec.front();
pBase->Print();
delete pBase;
return 0;
}
Like I said in my previous post; it's possible in some instances but perverse and not necessary. Also it only works because the memory layouts of both classes happen to be the same, an explicit specialisation could change this (like std::vector<bool> ).
Steve
|
|
|
|
|
Ok... Stephen Hewitt as from the start, you are moving to my direction, something like this is what i have.
I am talking explicitly about vector<something*> as i am handling all other types differently.
Well thank you, it didnt help me solve the problem but it did help me to abandon the idea that something is
wrong with cast (unless someone will say something that explains why i shouldnt do it).
(i dont know if those "rate" points are helpfull to you but anyway i will give you 5 for both posts)
|
|
|
|
|
yeti11 wrote: but it did help me to abandon the idea that something is
wrong with cast
Don't abandon this idea; the cast is perverse and is asking for trouble. The troubles you’ll encounter with this type of thing are amongst the hardest to track down. In short, you’re short-circuiting the compiler’s type checking so a whole class of problem that would normally result in compiler errors now result in runtime errors instead. It was not my intention to encourage bad design.
Steve
|
|
|
|
|
"It was not my intention to encourage bad design."
Well, we shall see, i'll gladly post the results here I know it is
hack but it saves so much complications, not to mention that it keeps
code nice and clean, alternative i was thinking about is to do my own
template that would internally store vector<mybase*> but on the
outside casts will be made on [] and at(). Instead of storing pointer
to this "wrapper" template i will store pointer to internal vector and
as internally the type is allways the same, but on the outside it is
still used as it was. In any case this is gonna be firmly tested, if
it fails i'll know.
imho, as far as i can logically think about the cast, there should be nothing
wrong with it. Actually i am casting from vector<dword>* to vector<dword>*
|
|
|
|
|
As I said, in your case it will work. Nevertheless, in general, it is an unforgivable design decision. I’ve also mentioned that template specialisation could also invalidate this construct although the chances of this occurring are fairly slim. If was an employer and one of my employees done this without a bloody good reason I’d fire him on the spot. Naturally their are exception to every rule but in general there is very little places you need to pull this kind of hackery.
Steve
|
|
|
|
|
Damn, do you never sleep?
Ok, ok, lets say you convinced me, i am gonna write freaking templates today (*grumble*),
although i am still pissed of that this should be declared as a hack.
I hate templates and i believe at the end there is allways a good reason not to use them
(speed, redundancy in binary, MESS) but unfortunally this time i was pushed into them as
too much code depending on them to change it. Oh well, its a living
|
|
|
|
|
I think templates kick ass. If you use them right runtime speed is one of the advantages of templates.
Steve
|
|
|
|
|
Yeah i forseened that Well have a nice day/night...
|
|
|
|
|
I have read your post and the answers to it, before posting mine:
1) Do not do that!
2) Do not even think about doing that!
3) If you have to, then redesign it so that it is not required.
Why don’t you just use a virtual base class and store a pointer to that in the vector?
class A
{
public:
A() {}
virtual ~A() { std::cout << "destroying class A" << std::endl; }
virtual print() const { std::cout << "class A" << std::endl; }
};
class B : public A
{
public:
B() {}
virtual ~B() { std::cout << "destroying class B" << std::endl; }
virtual print() const { std::cout << "class B" << std::endl; }
};
int main()
{
std::vector<A*> a_vec;
int i;
for( i=0; i<3; ++i )
a_vec.push_back(new B);
for( i=0; i<3; ++i )
a_vec[i]->print();
for( i=0; i<3; ++i )
delete a_vec[i];
return 0;
}
Then if you need to access a method that is in a derived class that is not defined in the base class, use dynamic_cast . You can check the pointer, returned by the cast, to insure that it is not null, which would indicate that the cast would be invalid.
I hope that helps.
INTP
"Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
|
|
|
|
|
Thank you for the answer, but i would rather point to 1) and 2) WHY?
|
|
|
|
|
Better late than never!
1) It overly complicates a simple operation and any methods available in the base class are also available in the derived class, unless the base class was declared private; in which case I would hope the complier rejects it. The idea is to find the simplest overall solution to a problem, making it easier to understand and implement. Except in a very narrow niche, this type of conversion should be avoided as it can introduce unexpected side effects.
2) Well that was a bit of an over statement. I can see thinking about it, but my mind automatically rejects that line of thought as anything more than a means to better understand the language.
If you need to store pointers to the derived class in a vector, other than a vector of base class pointers, then use dynamic_cast to convert the individual pointers on a per pointer bases, as needed. I do feel though that if you need to do this, then there is a fundamental flaw in the design.
INTP
"Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
|
|
|
|
|
Hello, everyone, I'm a beginner of windows programming. Now I've got a problem on thread.
I wrote the following codes:
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hT1;
hT1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);
CloseHandle(hT1);
cout<<"main thread"<
|
|
|
|
|
Firstly, you shouldn't be using CreateThread to start a thread that uses CRT functions. Use _beginthread or _beginthreadex . See this[^] page (near the bottom) for official confirmation on this.
Note that calling CloseHandle on a thread doesn't stop the thread executing.
As for the timing, you can't really make too many assumptions about the thread scheduling, but your result don't surprise me.
Steve
|
|
|
|
|
Thank you a lot, Steve. You comments are really helpful. I need to do more research on it.
One more question: the "thread schedule" you mentioned. do you mean the time when the worker thread is executed is uncertain?
Thank you!
-- modified at 22:39 Sunday 14th January, 2007
Jeffrey
|
|
|
|
|
The scheduling will depend on many things, some of which are:
- The priorities of each thread.
- The number of CPUs (or cores in multi-core CPUs).
- The number of threads in the system.
- The OS.
Steve
|
|
|
|
|
Hmm, looks like I need to go through some OS stuff to make it very clear.
Thank you, Steve!
Jeffrey
|
|
|
|
|
Basically, you shouldn't assume much about the scheduling of threads beyond the simple things such as threads with higher priorities will be run in preference to threads with lower priorities and the scheduler will be “fair” amongst threads with the same priorities. If you need finer control you should use synchronization objects such as CRITICAL_SECTION s and the like.
Steve
|
|
|
|
|
To learn the basics and avoid common pitfalls regarding multithreading, read Joe Newcomer's article on the subject here[^].
"It's supposed to be hard, otherwise anybody could do it!" - selfquote
|
|
|
|
|
wrote: int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hT1;
hT1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);
WaitForSingleObject(hT1, INFINITE);CloseHandle(hT1);
cout<<"main thread"<<endl;
return 0;
}<="" blockquote="">
In this way - for example - you let the thread execute and wait for thread to finish, then back in main thread and this will finish, too.
Output will be
thread1
main thread
Nuclear launch detected
|
|
|
|
|
wrote: I expected only "main thread" would be printed out, coz the main thread quits before Thread1 can be executed.
You're still thinking of things as synchronous. Windows, and especially threads, are a fundamentally asynchronous, event-driven universe.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
I don't know how to build a class of a large number. It maybe include hundreds number characters. Its behaviour are "*(x)" , "+", "-" , "/".
Somebody helps me.
Thanks alot.
Try to find how to die
|
|
|
|
|
rockfanskid wrote: I don't know how to build a class of a large number. It maybe include hundreds number characters. Its behaviour are "*(x)" , "+", "-" , "/".
Somebody helps me.
|
|
|
|
|
I did this once a long time ago in C. I just recently converted it to VC++. Which part are you having trouble with?
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
So I have a program that reads a network source in over a TCP/IP connection and it sends info between 10 times a second and once every 10 seconds. Now, at first, I thought I could just use a Timer and every time it ticks, call my recv() function. However, it works until like the fifth time I call recv() and that's when it freezes the program and stops updating. I was wondering if there is any way to make the program call recv constantly, without blocking, so it can update the program whenever the network source send information, but not freeze the program when the network source doesn't send any info. Any suggestions?
Oh yeah, I'm using Visual Studio 2005 on Windows XP, and I'm using Windows Forms to write it. Let me know if I'm unclear about something.
|
|
|
|