|
First assume
objectPtr->leftPtr = 1111
and
smallObject->leftPtr = 2222
then
BlitzPackage wrote:
objectPtr->leftPtr = smallObjectPtr->leftPtr
will assign the value of 2222 to objectPtr->leftPtr
while
BlitzPackage wrote:
*objectPtr->leftPtr = *smallObject->leftPtr
This will assign the contents of the object pointed to by smallObject->leftPtr to the object pointed to by objectPtr->leftPtr. In otherwords it will call the assignment operator [i.e. the OtherObject::operator=(const OtherObject&) function].
BlitzPackage wrote:
objectPtr->leftPtr = *smallObject->leftPtr;
Is there anything wrong here? That depends on the definition of the class OtherObject. But the answer is usually, yes. The diference is if the OtherObject class overrides the address-of operator (&) [i.e. the OtherObject* OtherObject::operator&() function], which would return the address of an OtherObject, premuably "this".
|
|
|
|
|
Thanks Ahz. I appreciate your answer and will continue to ruminate over it. Pointers are indeed one of the most challenging parts of C++ to understand, but it is nonetheless essential to so much else that I must master it.
Thanks again.
|
|
|
|
|
Hi,
if you don't like pointers have a look at references (int&).
The main difference is: You can't have NULL references.
Regards
Achim Klein
We can do no great things, only small things with great love. - Mother Theresa
|
|
|
|
|
Achim,
Can you implement binary trees (and other data structures) with references?
It's just a matter of time!
|
|
|
|
|
I tend to 'no', but I'm no professional.
The crucial point is that you can't leave references uninitialized.
If you have a class like this:
class Node
{
Node& l;
Node& r;
};
You need a constructor like:
Node::Node(Node& Left, Node& Right)
: l(Left),
r(Right)
{
...
}
This means: 'You can only create a new Node, if you already have two other Nodes'.
We can do no great things, only small things with great love. - Mother Theresa
|
|
|
|
|
Hi,
You can't create a reference data structure in the same way you would with a pointer data structure. With pointers the compiler does not need to know what the object methods/vars are inorder to point to it. Hence the NULL pointer. As soon as you dereference the pointer you will be accessing the object, just pointing to it is no problem.
However with a reference, you are already "dereferencing a pointer" at compile time as it were. A reference stores the memory address of the object so there needs already to be a memory address for the object. Hence data structures that need to have a copy of themselves can't be just re-written easily. In the example about you would never be able to create a Node object because you would always need a Node to begin with, that Node would need another Node before it, and so on. A vicious circle.
The way around all this is to create some sort of container for the nodes.
class NodeCont
{
public:
NodeCont (void) : m_fIsNull (true) { }
void Set (void) { m_fIsNull = false; }
bool IsNull () { return fIsNull; }
protected:
bool m_fIsNull;
};
Your actual data node could be inheritered from this class. Then your Node class would be easy to update:
class Node
{
public:
Node (NodeCont& left, NodeCont &right) : l (left), r (right) { }
NodeCont& l;
NodeCont& r;
};
For NULL nodes you would just need to check the IsNull function. The trick now is to create presistant memory (memory not on the stack) for all the containers. e.g.:
NodeCont *left = new NodeCont;
NodeCont *right = new NodeCont;
Node N (*left, *right);
And that is how you can get around pointers if you really want to.
regards,
Rich
"Programming today is a race between software engineers striving to build bigger and
better idiot-proff programs, and the Universe trying to produce bigger and better idiots.
So far the Universe is winning." -- Rich Cook
|
|
|
|
|
Hi Richard,
this looks like a really smart approach.
Thanks for sharing your ideas.
Regards
Achim Klein
We can do no great things, only small things with great love. - Mother Theresa
|
|
|
|
|
Hi,
1) What is the difference between the following two declations:
a) *objectPtr->leftPtr = *smallObject->leftPtr
b) objectPtr->leftPtr = smallObjectPtr->leftPtr
In an expression like int* pVal = &Val; you always have 2 involved objects:
- the 'real' object (here: int Val (defined anywhere else))
- the pointer (here: int* pVal )
So, 1a) will copy the content of your 'real' objects as follows:
objectPtr->leftPtr->memberA = smallObject->leftPtr->memberA;
objectPtr->leftPtr->memberB = smallObject->leftPtr->memberB;
objectPtr->leftPtr->memberC = smallObject->leftPtr->memberC;
If OtherObject has a Copy-Constructor 1a) will call it.
And 1b) will copy the content of your pointers (the numerical adress values).
2) How can I tell which one to use?
Depends on what you want to do:
- if you want to copy the content of your object, use 1a)
- if you want to have two pointers pointing at the same object, use 1b)
3) Finally, is there anything wrong with the following declaration and what does it mean (or vice versa regarding the "*" dereference):
Your VC++ compiler should give you a C2440 error.
This line says: OtherObject* = OtherObject . It's like int* = int . Obviously this can't work.
Regards
Achim Klein
We can do no great things, only small things with great love. - Mother Theresa
|
|
|
|
|
Thanks Achim Klein. I appreciate you taking the time to respond. That's more good information.
|
|
|
|
|
Achim Klein wrote:
If OtherObject has a Copy-Constructor 1a) will call it.
Naaah. I suppose you mean copy assignment operator. This invokes the copy constructor: A secondA = firstA if firstA is of type A .
--
The Blog: Bits and Pieces
|
|
|
|
|
Hi Johann,
you're absolutely right. The statement given in 1a) just calls the assignment operator OtherObject& operator=(const OtherObject& Obj) if there is one.
Sorry for that mistake.
Regards
Achim Klein
We can do no great things, only small things with great love. - Mother Theresa
|
|
|
|
|
The basic thing to remember about a pointer of type A* is that it either points at nothing (NULL ) or to a memory address where a chunk of memory resides which size is an even multiple of sizeof(A) .
Imagine a part of the memory space, where an A[4] array resides and a pointer A* pA which points at the first of these A s:
A chunkA[4];
A* pA = A; And this looks like:
| | | | | | |A|A|A|A| | | | | | | |
|_|_|_|_|_|_|0|1|2|3|_|_|_|_|_|_|_|
^
|
|------------- pA Now we can say
A a0 = *pA++;
A a1 = *pA++;
A a2 = *pA++;
A a3 = *pA; Stepping pA once more would take it outside the A[4]. Since we don't know what is there, we don't want to dereference pA if it points there, e.g.:
A a3 = *pA++
A a4 = *pA; have small chances of resulting in expected behavior...
The expressions (a) - (d) will all invoke the copy constructor of A, which in the default case will invoke the copy constructor for all its members that have a copy constructor and make a binary copy of pod mebers that lack copy constructors. Ad infinitum. Sort of.
--
The Blog: Bits and Pieces
|
|
|
|
|
I have a .Net Managed C++ wrapper control for a MFC control. When using the
.Net control in a Visual Studio 2005 Beta 2 C# project and running in Debug
mode, I get a crash saying something like "First Chance Exception : memory
cannot be read". I found that this was becuase a call to AfxGetThread() was
returning NULL. I tried using AFX_MANAGE_STATE(AfxGetStaticModuleState());
but it did not solve the problem.
Furthermore, this crash only occurs in Debug Mode and not in Release Mode.
Also, this occurs only in VS.Net 2005 Beta 2 and not in VS.Net 2003 ( either
release or debug)
How can this be resolved?
|
|
|
|
|
Hi All,
I am calling a pure virtual function in a constructor and the linker is complaining that there is no function definition. The scenario is this:
class base
{
base (void) { f1 (); }
virtual void f1 (void) = 0;
}
class child : public base
{
child () { }
void f1 () { cout << "This should print" << endl; }
}
The linker complains that there is no f1 function defined. If I move the call to another function and call f1 then there is no problem.
Does anyone know a way around this?
regards,
Rich
"Programming today is a race between software engineers striving to build bigger and
better idiot-proff programs, and the Universe trying to produce bigger and better idiots.
So far the Universe is winning." -- Rich Cook
|
|
|
|
|
In C++, you shouldn't call virtual functions from the constructor or the destructor. The derived class's functions are updated in the virtual table only when their constructor runs. The base class's constructor runs before the derived class's, so during execution of the base class constructor, only the base class implementation of the virtual functions will be available.
In your case, it happens to be pure virtual and so the linker is complaining. The only way I know around this is to call a base class function (equivalent to the constructor) from every derived class's constructor. Ugly and I'm not sure it's standard C++ behavior, but it works because at that point the derived class has already set up the vtable for it's overridden virtual functions.
Regards
Senthil
_____________________________
My Blog | My Articles | WinMacro
|
|
|
|
|
Thanks for the info. I had always wondered about the v-table that appears in the VC debugger.
regards,
Rich
"Programming today is a race between software engineers striving to build bigger and
better idiot-proff programs, and the Universe trying to produce bigger and better idiots.
So far the Universe is winning." -- Rich Cook
|
|
|
|
|
|
Thanks for the site, some good info to know
regards,
Rich
"Programming today is a race between software engineers striving to build bigger and
better idiot-proff programs, and the Universe trying to produce bigger and better idiots.
So far the Universe is winning." -- Rich Cook
|
|
|
|
|
Hello,
I want to know how I can convert ASCII strings into their Hex Values. For example:
A = 41
K = 4B
I'm programming with Dev-C++ if this is any help.
With best regards,
Benedikt
|
|
|
|
|
Hi there,
This might sound silly but you just need to cast them to an int e.g.:
const char string[] = "test string";
for (int i = 0; string[i] != '\0'; ++i)
printf ("Hex 0x%x\n", (int) string[i]);
regards,
Rich
"Programming today is a race between software engineers striving to build bigger and
better idiot-proff programs, and the Universe trying to produce bigger and better idiots.
So far the Universe is winning." -- Rich Cook
|
|
|
|
|
I think he meant converting the string representations of a hex value to the actual hex number, not the hex of any character value.
--
The Blog: Bits and Pieces
|
|
|
|
|
Oh, try this then:
const char string[] = "test string";
char hexstring[200];
hexstring[0] = '\0';
for (int i = 0; string[i] != '\0'; ++i)
sprintf (hexstring, "%s %x", hexstring, (int) string[i]);
This will create a hex list of all the characters in string .
regards,
Rich
"Programming today is a race between software engineers striving to build bigger and
better idiot-proff programs, and the Universe trying to produce bigger and better idiots.
So far the Universe is winning." -- Rich Cook
|
|
|
|
|
...still not quite there
I'm quite sure he meant this that he has a string "D4", which without the quotes is the hex number D4. He wants to get the hex number D4, not the hex for the value of the characters 'D' or '4'. There are lots of ways to do this. I'll punch a couple out later tonight when I have time to concentrate better.
--
The Blog: Bits and Pieces
|
|
|
|
|
Can anyone plz help with the implementation of the following member functions.
1.void EmployeeDatabase::getEids(vector <int> &ids)
2.string EmployeeDatabase::getName(int employeeID)
3.double EmployeeDatabase::getShoeSize(int employeeID)
<code>
#include "EmployeeDatabase.h"
#include<vector>
using namespace std;
EmployeeDatabase::EmployeeDatabase()
{
size = 0;
}
/*void EmployeeDatabase::getEids(vector <int> &ids)
{ // Complete the code.
//int iter;
//iter = v.assign(ids, people);
for(int i = 0; i<=ids.size( ); i++)
{
}
return ids;
}
*/
/*string EmployeeDatabase::getName(int employeeID)
{// Complete the code.
// Returns the name of the Person with eid equal to employeeID.
//string TheEmployees;
}*/
double EmployeeDatabase::getShoeSize(int employeeID)
{// Complete the code.
// Returns the shoesize of the Person with eid equal to employeeID.
}
void EmployeeDatabase::makePerson(string employeeName, int employeeID, double employeeShoeSize)
{
vector <Person> m_Staff;
Person people(employeeName, employeeID, employeeShoeSize); // this assumes a class called person with this constructor signature
m_Staff.push_back(people);
}
int EmployeeDatabase::getSize()
{
return size;
}
</code>
here is the application test program I have to test the member functions.
<code>
#include "Person.h"
#include "EmployeeDatabase.h"
#include "Data.h"
#include<iostream>
#include<fstream>
using namespace std;
int main(){
EmployeeDatabase TheEmployees; // These two commands make the data in the database Data.o available
Data DB(TheEmployees); // Include these two commands at the beginning of your program, and
// then use the methods from EmployeeDatabase to get the data.
vector<int> ids;
TheEmployees.getEids(ids);
cout << "The Eid of the first employee is " << ids[0] << '\n';
cout << "The name of the first employee is " << TheEmployees.getName(ids[0]) << '\n';
cout << "The shoe size of the first employee is " << TheEmployees.getShoeSize(ids[0]) << '\n';
pause();
}
</code>
|
|
|
|
|