|
I got it. Thank you for all your help.;) It help to have perspective
Dove
#include <iostream.h>
#include "Cat.h"
#include "Dog.h"
void speak(CCat c);
void speak(CDog d);
void main()
{
CCat cat1;
CDog dog1;
cat1.catname = "Felix";
dog1.dogname = "Fido";
speak(cat1);
speak(dog1);
}
void speak(CCat c)
{
cout << c.catname << " says meow " << endl;
}
void speak(CDog d)
{
cout << d.dogname << " says woof " << endl;
}
|
|
|
|
|
Why don't you use a dummy argument in the second speak function i.e. to overload it like it is used for pre/post increment/decrement operators
void speak(char *str); //For cat object
void speak(char *str, int dummy);//For dog object
Really speaking an elegant solution is as Christian suggested using inheritance / virtual functions...
---------------------------
Atul
|
|
|
|
|
I understand you're suggesting this as a last resort to try and get the desired behaviour, but I just *have* to say for the record that I thought this to be fairly obvious, but too ugly to suggest
I realise you're not suggesting it as a real world solution, so please don't be offended
Christian
#include "std_disclaimer.h"
People who love sausage and respect the law should never watch either one being made.
The things that come to those who wait are usually the things left by those who got there first.
|
|
|
|
|
No offence taken as the code is indeed ugly and does not even count as the last resort in real world probs. But as he suggested he had to do it according to the book so the suggestion...
Should include a disclaimer...
|
|
|
|
|
Hmm.. I think this is what your exercise want you to do!
void speak (CCat s)
{
cout << "Shut the f*** up! I'm trying to get a moment of rest here!!\n";
}
void speak (CDog s)
{
cout << "Woof!\n";
}
// ^ You overload the "speak"-function with different acts
//
// The compiler will automatically choose the "speak" matching
// your arguments.
int main [..blabla..]
{
CCat cat1;
CDog dog2;
cout << "The dog says.. ";
speak (dog1);
cout << "And the cat goes..";
speak (cat1);
}
Hope this will do the trick!
Gustav Tresselt
|
|
|
|
|
int main [..blabla..]
{
CCat cat1;
CDog dog2;
^
should be "dog1", as you probably understood..
And this bloody list message handler is sensoring my f***ing swearing!
|
|
|
|
|
As most of you probably know, my niche is graphics. However, I spent the weekend making a VC++ add in that allows me to set named breakpoints ( I can't make the ones included work ) and it's the beginning of a system that will link into our bug tracking system, so we can log bugs and view their history from within VC. I intend to build a database that holds this information, because I want inclusion into our bug tracker to be optional. My question is, if I use ADO, can I ask it to *create* the database for me, or do I need to provide the file for it to manipulate ?
If the latter, I will need to 'install' my system and store it's location so I can copy across an empty database for each new project, but I'm hoping a more elegant solution will present itself...
Ta.
Christian
#include "std_disclaimer.h"
People who love sausage and respect the law should never watch either one being made.
The things that come to those who wait are usually the things left by those who got there first.
|
|
|
|
|
With MSSQL, you could connect to master, then issue some SQL calls like "CREATE DATABASE" and you're done. But it seems you're using some file-oriented db like Jet.
Tomasz Sowinski -- http://www.shooltz.com.pl
|
|
|
|
|
... and I've also found the way to create empty Jet database using ADOX. There's an sample in Platform SDK/Data Services/MDAC SDK/ADOX Programmer Reference/Code Examples in VC/Create Method Example.
Tomasz Sowinski -- http://www.shooltz.com.pl
|
|
|
|
|
Thanks so much - I'll give this a try then.
Christian
#include "std_disclaimer.h"
People who love sausage and respect the law should never watch either one being made.
The things that come to those who wait are usually the things left by those who got there first.
|
|
|
|
|
Hello, the codegurus around the world?;)
What means "create the database"?
We can put the all data in only one table.
But, this isn't good implementation of the database.
It is difficult for us to create the schema of the database, so
we need the database administrator to create the database.
As long as we create only one table to restore your data, we can use SQL statement
in ADO.
It works for me to create the new table in MSDE or Access Database.
However, if we create more tables, and use the foreign keys,
we must need to check the order of creating the table and insert the data safely.
I think that we can use SQL statement at any database class like ODBC, DAO, ADO and OLE DB.
Last, my database knowledge is a level of the database class of CIS (the graduate course).
So, I may miss something important.
Have a nice day!
-Masaaki Onishi-
|
|
|
|
|
I was wondering if we can hook or if we can see what are the connections currently made on the computer? I was particulary interested in the HTTP connections on the port 80. I want to be able to know where the person is surfing in real time on the computer. I don't know if it is possible to do that.
Crocmort
|
|
|
|
|
This is possible by using SNMP (Simple Network Management Protocol) interfaces DLL and having the same functionality of Netstate and looking at the target address when the port is 80
For source code of doing the netstat see sysInternals
TCPview
There is also ways of using your own Service Provides and trapping for all winsock functions.
Kindest regards
Alfadhly
<marquee>
It is Illogical to define an inventor by his invention
|
|
|
|
|
in ATL's CSimpleArray:
class Wrapper
{
public:
Wrapper(T& _t) : t(_t)
{
}
template <class _Ty>
void *operator new(size_t, _Ty* p)
{
return p;
}
T t;
};
void SetAtIndex(int nIndex, T& t)
{
ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
new(&m_aT[nIndex]) Wrapper(t);
}
Why
-Ben
"Its funny when you stop doing things not because they’re wrong, but because you might get caught." - Unknown
|
|
|
|
|
Hey Ben
This is a form of placement new. For example, the Add method makes space for the new object then calls SetAtIndex. Looks like the Wrapper class serves to provide the placement new, which allocates no space, and initialize the object by calling the ctor in the initialization list of the Wrapper constructor.
I think the basic idea behind placement new is efficiency - memory is allocated from a pool managed by the class, and new entries can be just added in and the count incremented. In this case, I guess things are additionally complicated by the templated type allocation, hence the need for the Wrapper.
There's probably a pattern here that some STL gurus would recognize - bet you could get a better explanation on comp.lang.cpp.moderated.
I'd like to understand this better myself - wonder if this kind of thing is standard practise in STL containers as well, or if there are other abtuse tricks afoot...
T
|
|
|
|
|
SetAtIndex creates new 'wrapped' object using placement new, but where's the destructor? I mean, if you call SetAtIndex and pass the index of already existing array element, the previous content should be deleted, right? Unfortunately, I don't have CSimpleArray sources - can't single-step through the code. The code posted here has a debug build index check and call to placement new.
Tomasz Sowinski -- http://www.shooltz.com.pl
|
|
|
|
|
Check out ATLBASE.H.
If you look at Add, RemoveAt, and RemoveAll you'll see where the space allocations are maintained, and dtors are explicitly called.
|
|
|
|
|
> Check out ATLBASE.H.
No such luck today I'm currently using a machine without any dev tools installed. Will have look tomorrow - SetAtIndex looks interesting.
Tomasz Sowinski -- http://www.shooltz.com.pl
|
|
|
|
|
Explicit dtor is missing from the SetAtIndex - every time SetAtIndex is called one object is 'wiped out' without invoking the dtor. Looks and feels like bug. CSimpleArray is a cheap kludge anyway - all data members are public, you can't pass const references as arguments to methods like Find, etc.
The code below demonstrates the problem with SetAtIndex:
#include <stdio.h>
#include <atlbase.h>
int ctorCalls = 0;
int dtorCalls = 0;
class Elem
{
public:
Elem() { value = 0; ctorCalls ++; Diag("def ctor"); }
Elem(const Elem& other)
{
value = other.value;
ctorCalls ++;
Diag("copy ctor");
}
~Elem() { dtorCalls ++; Diag("dtor"); }
void SetValue(int newValue) { value = newValue; }
private:
void Diag(const char *fxn)
{
printf("%s, this=%x, value=%d\n", fxn, this, value);
}
int value;
};
void test()
{
CSimpleArray<Elem> array;
Elem e;
e.SetValue(11);
array.Add(e);
e.SetValue(22);
array.Add(e);
e.SetValue(33);
array.Add(e);
e.SetValue(44);
array.SetAtIndex(1, e);
}
void main()
{
test();
printf("ctor calls: %d\ndtor calls: %d\n", ctorCalls, dtorCalls);
}
Tomasz Sowinski -- http://www.shooltz.com.pl
|
|
|
|
|
I dont think SetAtIndex is intended to be used outside the context of Add.
Since the primary purpose (documented anyway) of CSimpleArray is to provied a record container for CRowsetImpl, we could probably look at how its used there. I would imagine it's treated like CSimpleValArray, which pares down the interface to the working norm of Add(), operator[](), and Remove().
Found this in the MSDN as well - but haven't looked at it:
The CMSPArray template implements a smart array that will grow on demand. It is designed to hold small arrays with simple data types. It doesn't have a critical section. Its only dependencies are realloc and memmove. It is used internally to keep lists of object pointers. It is similar to ATL 2.1's CSimpleArray implementation, but it is more efficient for initial allocations.
This template is defined in MSPutils.h.
|
|
|
|
|
Thanks Tim, it make a little more sence now, but I'm not usre is see that its more efficient. Maybe its a way to allow object's with no copy operator to be copied?
-Ben
"Its funny when you stop doing things not because they’re wrong, but because you might get caught." - Unknown
|
|
|
|
|
> Maybe its a way to allow object's with no copy operator to be
> copied?
You mean the assignment operator, right? Yes, this method makes it possible. You're creating new objects at address CSimpleArray already knows. The class you're storing in CSimpleArray only needs public copy constructor.
Note that SetAtIndex has a bug: it doesn't explicitly invoke destructor for 'previous' object - the one that occupied nth index before calling SetAtIndex. For more details check my reply to Tim in this thread.
Tomasz Sowinski -- http://www.shooltz.com.pl
|
|
|
|
|
I took a look at the CMSPArray in MSPutils.h (platform SDK includes). Looks like it could have been cloned from CSimpleArray, or vice versa, save for a few calls. The most notable difference is that it doesn't bother supporting non POD types - no ctors or dtors are called.
In this class, the line in SetAtIndex you highlighted in your original post is simply
m_aT[nIndex] = t;
So, the whole trick seems to boil down to basing a simple container on realloc and memmove while supporting non POD types. If you were to start from CMSPArray and add support for non POD types, you might wind up with CSimpleArray - but that Wrapper class sure is a brain twist.
As for effeciency, I think it probably depends on the context, types stored, etc. Maybe as a container for hundreds of recordsets CSimpleArray is a good choice.
later
Just occurred to me that another difference from this and a standard container is the lack of the need for a defined operator < for its types - again, makes sense for a simple array of things like db records.
|
|
|
|
|
Hi
I need to know if anyone have good VC++ Source for a Cataloguer like "Advanced Disk Catalog" or any good reference site ?
TIA
BLaZe
|
|
|
|
|
to compare 2 strings one uses strcmp, but what about integers? is there a strcmp alternative for int/float?
check out the code see what i mean
void binSort(FILE * pt, int struSize, int n)
{
float i, j, minPos;
struct Planet iRec, jRec, temp;
for(i = 0; i < (n-1); i++)
{
fseek(pt, 0L, SEEK_SET);
fseek(pt, (i*struSize), SEEK_CUR);
fread(&iRec, struSize, 1, pt);
for(j = (i+1); j < n; j++)
{
fseek(pt, 0L, SEEK_SET);
fseek(pt, (j*struSize), SEEK_CUR);
fread(&jRec, struSize, 1, pt);
if(strcmp(jRec.diameter, iRec.diameter) < 0)
{
temp = iRec;
iRec = jRec;
jRec = temp;
fseek(pt, 0L, SEEK_SET);
fseek(pt, (i*struSize), SEEK_CUR);
/*swap records*/
/*fwrite(&iRec, struSize, 1, pt);*/
printf("iRec = %fn", iRec);
fwrite(&iRec, struSize, 1, pt);
fseek(pt, 0L, SEEK_SET);
fseek(pt, (j*struSize), SEEK_CUR);
fwrite(&jRec, struSize, 1, pt);
}
} /*end j*/
} /*end i*/
}
its all good until 'if(strcmp(jRec.diameter, iRec.diameter) < 0)'. since jRec/iRec.diameter are declared as floats i get mismatch errors. im working with structures, files, etc, so i wanna know if there are any strcmp alternative or do i have to code a seperate function?
|
|
|
|
|