|
Passing/returning by value has disadvantages:
1) there's a copy created with a call to copy constructor. While this isn't a problem for built in types like int or double or small structs like POINT, it may significantly hurt performance for other objects, especially ones which allocate memory in constructor (std::vector, for example).
2) polymorphism may be lost. When you have function like this...
ISampleData Acquire()
{
CImage result;
...
return result;
}
CImage image = Acquire();
... then the 'result' variable doesn't reach 'image'. Instead, temporary object of type ISampleData is created (it may be impossible when ISampleData has pure virtual methods) and copied again into 'image'. Your cast to CImage& is simply cheating, in fact, on the right side of '=' you don't have CImage object anymore.
Bertrand Boichon wrote:
Instead, I'd like to copy the object created in "Acquire", into the object "image" (i.e. "image = m_lpDigitizer->Acquire();").
That is: using the stack, not the heap.
You'd have to return CImage, not ISampleData. As I said above, this may be quite inefficient, however.
Tomasz Sowinski -- http://www.shooltz.com
*** Si fractum non sit, noli id reficere. ***
|
|
|
|
|
Ok... more questions:
First of all, what do you mean CImage& is cheating? I mean, to me, it seems logical to use the reference (address in memory) of a CImage object (base on ISampleData interface), since I cannot return an instance (by value) of type ISampleData (pure abstract class).
Secondly, what do you mean by "inefficient"? Passing/returning by value versus by reference?
The other possiblity is to create the object on the heap (with new) and pass/return the pointer by value, like this:
ISampleData* Acquire()
{
CImage* result = new CImage();
...
return result;
}
CImage* image = (CImage*) Acquire();
But then I thought doing that is less "efficient" than copying an object to the 'caller' stack (by returning a reference to a CImage obj)????
The other thing is:
Surprisingly (and I thought the same as you did) polymorphism is NOT lost, and I don't know why...
I made a little experiment: I created a method in my class CImage called Display() which is not overloaded from CSampleData (i.e. just a new method specific to CImage). Then I did exactly as before (with "Acquire()" returning a reference to ISampleData):
CImage image = (CImage&) m_lpDigitizer->Acquire();
And guess what? when I call "image.Display()", well it works fine!
Why? Is it because I am dealing with reference to an object, not the object itself. Polymorphism apply to an object copy (by value), not to a reference copy of it?
Bertrand Boichon
|
|
|
|
|
Bertrand Boichon wrote:
Secondly, what do you mean by "inefficient"? Passing/returning by value versus by reference?
Yes. This is one of C++ basics. Of course, the 'inefficiency' greatly depends on the structure of class. Just remember that each object returned/passed by value is *copied*, and this can be quite expensive.
Could you post the Acquire function; simplify the actual code if needed but leave return type unchanged.
Tomasz Sowinski -- http://www.shooltz.com
*** Si fractum non sit, noli id reficere. ***
|
|
|
|
|
Here is the Acquire function, using a reference to a CImage (derived from ISampleData pure abstract class):
ISampleData& CCameraDigitizer::Acquire()
{
CImage sample;
// ... perform actual acquisition here ...
return sample;
}
The question is: what should I return ISampleData& (object by ref) or ISampleData* (pointer to obj, by value)?
I did some more tests on that matter (because I realized I don't know much about passing by reference vs by value). I added a dynamically allocated (on the heap) buffer (for the image itself) and an 'int' data field in the CImage class. Then I tried to use these in methods like Save or Display:
CImage image = (CImage&) m_lpDigitizer->Acquire();
image.Save("TEST.JPG");
image.Display();
I came to realize that even if Save and Display (using the buffer data field) are called correctly (what I saw at first), it actually displays crap since the buffer is pointing a random location, along with the 'int' field.
So the only solution is to return a pointer to a CImage obj (therefore allocated on the heap):
ISampleData* CCameraDigitizer::Acquire()
{
CImage* pSample = new CImage();
// ... perform actual acquisition here ...
return pSample;
}
And it works.
What do you think?
Best regards,
Bertrand Boichon
|
|
|
|
|
Returning the reference to local, non-static object is something you should *never* do in C++. The 'sample' variable is destroyed as soon as function returns - the CImage destructor is called. Your reference points to deallocated stack space which contains undefined bits.
So basically you have two options: allocated new object on the heap and return the pointer (as you did already) -or- pass the CImage object by reference to Acquire:
void CDigitizer::Acquire(CImage & image)
{
}
Tomasz Sowinski -- http://www.shooltz.com
*** Si fractum non sit, noli id reficere. ***
|
|
|
|
|
Is there any difference between returning and passing a reference to an object:
void Acquire(ISampleData& image)
vs
ISampleData& Acquire(void)
?
Because I tried the "ISampleData& Acquire(void)", and (of course) it de-allocates data fields when returning CImage reference. (cf previous email).
So you mean actually passing a CImage reference would not do that?
To me, the only option is to pass/return a pointer (to a CImage obj) by value.
bertrand
|
|
|
|
|
Bertrand Boichon wrote:
So you mean actually passing a CImage reference would not do that?
Yes, because you would not declare CImage inside Acquire:
void Acquire(ISampleData & image)
{
image.DoThis();
image.PerformThat();
}
...
CImage image;
Acquire(image);
The image Acquire is operating on is declared outside of function, so it's lifetime isn't bound to Acquire scope.
Returning a pointer to object allocated in Acquire is also OK. You may consider using std::auto_ptr or boost.org scoped_ptr to ensure proper deletion.
Tomasz Sowinski -- http://www.shooltz.com
*** Si fractum non sit, noli id reficere. ***
|
|
|
|
|
Thank you very much for the lesson!
Very helpful!
Bertrand Boichon
|
|
|
|
|
To enable / disable the toolbar buttons I use the update handler (ON_UPDATE_COMMAND_UI() macro)... ok... but when does the system change the state (enable/disable) of the toolbar buttons?
Have I to call Invalidate or UpdateWindow ???
--
Nice greets, Daniel.
|
|
|
|
|
'The system' (MFC app) updates the button state during its idle update cycle. See CWinApp::OnIdle and CFrameWnd::OnIdleUpdateCmdUI (undocumented).
Tomasz Sowinski -- http://www.shooltz.com
*** Si fractum non sit, noli id reficere. ***
|
|
|
|
|
Hi,
I would like use CMultiRectTracker into CScrollView to manipulate gdi
objects,
such as CRect, but when I try select object after scrolling there is bug
to move and positioning its RectTracker.
Can anyone help me?
Thanks, in advance
Gianfranco
|
|
|
|
|
Without any additional information about 'the bug', I guess you could forgot to convert from device units to logical units (with CDC::DPtoLP) in mouse event handlers.
Tomasz Sowinski -- http://www.shooltz.com
*** Si fractum non sit, noli id reficere. ***
|
|
|
|
|
I can get the select text in html in my ap. But how to get the position of the select text? Because next time I open the same html I want select the text auto.Or have any other way to do it?
|
|
|
|
|
This tag is part of the DOM, right ? So you need to store the path traversal from the root down to this node. It's up to you to find a convenient model. AFAIK, there's no such built-in model provided in the current IE DOM.
sometimes it helps to look at the IL generated code
a MS guy on develop.com "answering" .NET issues
|
|
|
|
|
So the html must have begin tag and end tag,if not. I would not do this feature right? Thx your reply.
|
|
|
|
|
Path traversal has nothing to do with end tags.
We are talking DOM IE API. That's just a matter of root node, and children.
She's so dirty, she threw a boomerang and it wouldn't even come back.
|
|
|
|
|
Sorry. I misunderstand. What is DOM IE API? Where I can find examples?
|
|
|
|
|
How can I change the bitmap of a toolbar button at runtime?
--
Nice greets, Daniel.
|
|
|
|
|
Try using the LoadBitmap() member function of CToolbar class.
|
|
|
|
|
Do you want to use any bitmap, or you just need to switch between some bitmaps you know at compile time?
Tomasz Sowinski -- http://www.shooltz.com
*** Si fractum non sit, noli id reficere. ***
|
|
|
|
|
Only between bitmaps I know at compile time (like a bitmap or a bitmap in a image list).
--
Nice greets, Daniel.
|
|
|
|
|
Use CToolBar::GetToolBarCtrl and CToolBarCtrl::AddBitmap to load bitmap from resource and append it to toolbar's image list, then CToolBar::SetButtonInfo to change the index of button's image. Bitmap should have the dimensions of your toolbar buttons, usually its 16 x 15. RGB(192, 192, 192) - light gray - is used as transparency by MFC toolbars.
Tomasz Sowinski -- http://www.shooltz.com
*** Si fractum non sit, noli id reficere. ***
|
|
|
|
|
Thanks... I try it...
--
Nice greets, Daniel.
|
|
|
|
|
How can I change the title of a dialog at runtime?
I want to add a constructor to my dialog, so that I can set the title of the dialog, like CMyDialog dlg(_T("Settings")); .
I save the title text in the constructor and want to set the title in the OnInitDialog function, but how can I set the title?
--
Nice greets, Daniel.
|
|
|
|
|
void SetWindowText( LPCTSTR lpszString );
|
|
|
|