|
Given the following code:
struct SLOT
{
CString sField1;
int nField2;
};
SLOT* m_pSlots[5];
void CMyClass::InitSlots()
{
for (int i = 0; i < 5; i++)
{
m_pSlots[i] = new SLOT;
if (m_pSlots[i])
{
m_pSlots[i]->sField1 = "Empty slot";
m_pSlots[i]->nField2 = i;
}
}
}
Would you say it is morte correct to say that m_pSlots is a pointer to an array, or that m_pSlots is an array of pointers?
My view is that it's an array of pointers, but my boss insists that it's a pointer to an array.
|
|
|
|
|
Aargh... the "pointers to pointers" syndrome.
Without looking at a C++ reference book or looking at the compiler output, my money is on your boss.
But then again...?
Stroustrup will hopefully give you the correct answer...
|
|
|
|
|
Stroustrup (2nd edition) says that using "[]" is the same as saying "array of" and using "*" is the same as saying "pointer to".
I think the interpretation of the code depends on the context in which the construct is used, and how you choose to organize it in your head. When I see this:
SLOT* m_pSlots[20];
I see an array of pointers to 20 SLOT objects. This is further supported by the way the code was written to access the array:
m_pSlots[0]->sField1 = "Text";
m_pSlots[0]->nField2 = 1;
In the context I gave, I view it as an array of 20 pointers to SLOTs. I personally don't see how it could be logically interpreted any other way, but I do recognize the fact that you can call it a pointer to an array, but doing so obfuscates the paradigm given the context in which the code exists, IMHO.
|
|
|
|
|
Back at work and armed with stroustrup and the compiler, I think there is only corect viewpoint: yours.
But talking about obfuscating code. I hope for your work buddies sake you’re not using this kind of C++-isms all over your code.
Completely beside the point, of course, but what is the advantage of your piece of code over the following code (and don’t say 'memory usage' please, because I will say 'speed'...) or did you just wanted to prove your point and embarrass your boss (and me)?
struct SLOT
{
CString sField1;
int nField2;
};
SLOT* m_pSlots = NULL;
void InitSlots()
{
m_pSlots = new SLOT[5];
for (int i = 0; i < 5; i++)
{
m_pSlots[i].sField1 = "Empty slot";
m_pSlots[i].nField2 = i;
}
}
void DeleteSlots()
{
delete [] m_pSlots;
}
int main(int argc, char* argv[])
{
InitSlots();
DeleteSlots();
return 0;
}
|
|
|
|
|
I think memory usage would be close (if not identical) because we are talking about a given struct within a finite array.
As for speed, I don't know if that would matter until we were talking about thousands of elements or hundreds/thousands or new/delete pairs.
And yes, I obfuscate my code like this all the time, and no, I wasn't trying to embarass anyone.
|
|
|
|
|
> I think memory usage would be close (if not identical) because we are talking about a given struct within a finite array.
~ Correct.
> As for speed, I don't know if that would matter until we were talking about thousands of elements or hundreds/thousands or new/delete pairs.
Actually, calling X times an allocation/de-allocation routine is almost ~X times slower than calling it once with a X-time larger memory chunk (provided it doesn't trash the OS). cfr. a good OS internals book, e.g. http://www.sysinternals.com/insidew2k.htm
> And yes, I obfuscate my code like this all the time, and no, I wasn't trying to embarass anyone.
Phew, thanks.
Since we are on a roll here: Do you want to stick your neck out? Try this one:
Write down the output of the listed program without compiling and running it. Then check the results...
But then again, of course, you do this in a jiffy.
class foo
{
public:
foo() {}
virtual ~foo() {}
virtual void Print(void)
{
cerr << "it's foo!\n";
}
void Print(int err)
{
cerr << "it's foo with err : " << err << "\n";
}
};
class childfoo1 : public foo
{
public:
childfoo1() {}
~childfoo1() {}
void Print(void)
{
cerr << "it's childfoo1!\n";
}
void Print(int err)
{
cerr << "it's childfoo1 with err : " << err << "\n";
}
};
class childfoo2 : public foo
{
public:
childfoo2() {}
~childfoo2() {}
void Print(void)
{
cerr << "it's childfoo2!\n";
}
void Print(int err)
{
cerr << "it's childfoo2 with err : " << err << "\n";
}
};
// which Print function is called ??
int main(void)
{
foo * foopointer1 = new childfoo1();
foo * foopointer2 = new childfoo2();
foo * foopointer3 = (childfoo1*) foopointer2;
childfoo1 * foopointer4 = (childfoo1*) foopointer2;
cerr << "\n1 ";
foopointer1->Print();
cerr << "\n2 ";
foopointer2->Print();
cerr << "\n3 ";
foopointer3->Print();
cerr << "\n4 ";
foopointer4->Print();
cerr << "\n5 ";
foopointer1->Print(5);
cerr << "\n6 ";
foopointer2->Print(5);
cerr << "\n7 ";
foopointer3->Print(5);
cerr << "\n8 ";
foopointer4->Print(5);
delete foopointer1;
delete foopointer2;
return 0;
}
|
|
|
|
|
m_pSlots is an array of pointers to SLOT.
One way I like to look at it, which isn't completely correct, but close enough, is to look at the contiguous storage. In your example, only the pointers are contiguous, the actual objects themselves are not.
If it were an array of objects, then the physical storage to each SLOT would be contiguous (though they can be contiguous without being an array)
Further examples of why it's an array of pointers is this code:
>m_pSlots[i]->sField1 = "Empty slot";
>m_pSlots[i]->nField2 = i;
Note that you are using the pointer dereference after the array dereference.
A pointer to an array would would look like this:
SLOT m_Slots[5];
SLOT* m_pSlots = m_Slots;
Which would then be dereferenced as:
m_pSlots[i].sField1 = "Emplty slot";
m_pSlots[i].nField2 = i;
(note the use of the member dereference (.) rather than pointer dereference).
|
|
|
|
|
Of course you are right. m_pSlots is array of pointers. Value of m_pSlots is the location of array in memory so it can be safely casted to a pointer to the array element type (in your example SLOT**). So if array declaration can be formally defined as
ElementType array[TheNumberOfElement]
dynamic creation can be formally defined as
ElementType* array=new ElementType[TheNumberOfElement]
and effectively array can be interpreted as a pointer to ElementType.
Then the pointer to array must be only interpreted as a pointer to a pointer to ElementType
|
|
|
|
|
How can I 'gray' an item in a menu?
If I set the properties of the menu-item gray, at run time, it will NOT be gray and disabled!
I tried to 'disable' it in the code with EnableMenuItem..., but it's also enabled.
Can someone help me?!!!
How can I disable or gray an item in a menu?!
Thank's
|
|
|
|
|
here is a short code
void CxxxApp::OnUpdateExpectEther(CCmdUI* pCmdUI)
{
if (BoolVar==TRUE) pCmdUI->Enable(FALSE);
else pCmdUI->Enable(TRUE);
pCmdUI->SetCheck(Var==1);
}
This code will enable/disable the menu-entry.
|
|
|
|
|
You don't mention whether you are using MFC or not. I will assume you are.
MFC will automatically gray any menu item for which you do not have a handler defined. If you do have a handler defined, but want to disable it, then you use the UPDATE_COMAND_UI mechanism. In the ClassWizard, create an UPDATE_COMMAND_UI handler for the command, then in the handler use the CCmdUI object passed to you to disable the item:
pCmdUI->Enable(FALSE);
|
|
|
|
|
In your code you can set the flags on the menu item you wish to enable/disable. Try these combinations:
1) To gray out: (MF_GRAYED | MF_STRING | MF_POPUP)
2) To enable: (MF_ENABLED | MF_STRING | MF_POPUP)
Then you can display the menu by using the following:
CMenu Menu;
Menu.CreatePopupMenu();
Menu.AppendMenu(Display_Flag, ID_D_STOREPRESET, _T(""));
Menu.AppendMenu(Display_Flag, ID_D_RECALLPRESET, _T(""));
Menu.AppendMenu(Display_Flag, ID_D_RENAMEPRESET, _T(""));
Menu.TrackPopupMenu(TPM_LEFTALIGN, X, Y, (CWnd *)this);
This is where Display_Flag is set equal to one of the two options above.
|
|
|
|
|
Can someone give me some guide on how to drag and drop file and folder on a TreeView.
I don't use MFC.
|
|
|
|
|
Hi,
How to change to text color and the background color of a combo box
|
|
|
|
|
You must set the color for the combobox, if the control send a Color-message.
HBRUSH CxxxView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor);
if ( pWnd->GetDlgCtrlID()==IDC_Status)
{
pDC->SetBkColor(SetColorRef(background)); //SetColorRef returns a RGB-value
hbr=m_hBrush[background]; //global defined brush-table
}
return hbr;
}
SFr
|
|
|
|
|
Is there any fast way to convert an MFC application into an ActiveX control or Com object?
|
|
|
|
|
Hi :
Not sure about what specifically you are asking for. Because it depends upon your app architecture.
Let me assume you are talking about a simple Dlg based Exe than Just Insert a new ATL object in it with all the default settings and here you go. Note that your app main thread can now be an owner of a COM object . Simply call CoCreateInstanceEx() from your client code and your COM object will be instantiated..
Anyway for your information.
Any object inherited from IUnknown is called a COM object and a COM object which is self registering is called an ActiveX control (simple is that)
|
|
|
|
|
thanks!
what I am trying to do is to move an existing document/view architecture MFC app into a form whereby it could be placed on an IE browser and do the same stuff...essentially, I have an existing MFC exe and I want to create an ActiveX out of it so it could be embedded into an html page and do the same stuff?
thanks
|
|
|
|
|
Hi, I am trying to display a bitmap in a SDI applicationg and for some reason it wont display the bitmap. Here is the code I am using. Any suggestions would be greatly appreciated.
CStatic myStatic;
myStatic.Create(_T("My Static"),
WS_CHILD|WS_VISIBLE|SS_BITMAP,
CRect(10,10,100+505,100+435),
this);
myStatic.SetBitmap( ::LoadBitmap(NULL, MAKEINTRESOURCE(IDB_BITMAP1)) );
Thanks for the help.
|
|
|
|
|
hInstance parameter (first one) from LoadBitmap should
be the instance of the module that contains the bitmap . In your case your application. You can use it as NULL only for predefined bitmaps like OBM_CLOSE.
Regrads,
/REMUS
|
|
|
|
|
Hi!
When I have built my program and executes the exec file my program looks for a database file I have connected to my program. The problem here is that the path to the file is hard coded so it looks for it in a certain location on the HD. What I want to do is charnge where it looks for the database. But I don't know how to get a string of the executive file. Is there any function that can get the execution path of this file?
I have found in the database file where it returns this path. I want to change it so that it gets the location where the .exe file is run.
Thank you for reading, (or even more importantly responding!
|
|
|
|
|
Here's three functions I use for getting the program path.
JustPath() - extracts the path from a string containing a filename.
AddBackSlash() - adds a backslash to the end of a string if it's needed.
GetProgramPath() gets the path and module filename of the running program (calls JustPath and AddBackSlash).
//------------------------------------------------------------------------------
Returns just the path if present of the specified filename string.
//------------------------------------------------------------------------------
CString JustPath(LPCSTR f)
{
char drive[_MAX_DRIVE],
dir[_MAX_DIR],
file[_MAX_FNAME],
ext[_MAX_EXT];
CString st;
_splitpath((char *)f, drive, dir, file, ext);
st = drive;
st += dir;
return st;
}
//----------------------------------------------------------------------------/
// Add a back slash to the end of the path if it doesn't exist.
//----------------------------------------------------------------------------/
void AddBackSlash(CString& path)
{
int length = path.GetLength();
if (length > 1)
{
if (path.GetAt(length - 1) != '\\')
{
path += "\\";
}
}
else if (1 == length)
{
CString temp = path;
temp.MakeUpper();
TCHAR ch = temp.GetAt(0);
if (ch >= 'A' && ch <= 'Z')
{
path += ":\\";
}
else if (ch != '\\') // add a back slash anyway
{
path += "\\";
}
}
else
{
path += "\\";
}
}
//-----------------------------------------------------------------------------/
// Get the path were the program was run from
//-----------------------------------------------------------------------------/
CString GetProgramPath(BOOL bStripFileName/*=TRUE*/)
{
CString sPath;
TCHAR szFullPath[MAX_PATH];
::GetModuleFileName(NULL, szFullPath, MAX_PATH);
if (bStripFileName)
{
sPath = JustPath(szFullPath);
AddBackSlash(sPath);
}
return sPath;
}
|
|
|
|
|
|
I am a jackeroo in WinCE and need you help very imminently!
my develop environment:
vc6.0 + WinCE toolkit for VC6.0
the configuration in my project
"H/PC Ver.2.00"
my target device:
cpu: MIPS
os: WinCE 2.11
Is there some problem in compatibility and what should I do?
Thanks a lot!
|
|
|
|
|
Are there any methods to implement a drag source on an application if it is not previously implemented? e.g. If IE does not support dragging an image, is it possible to implement it?
|
|
|
|