|
It does not matter, the methods that use the pointer need to cast it to the appropriate type. That's why I suggested using a union as both structures then occupy the same area of memory.
|
|
|
|
|
Can you please give me a small example of declaring the second struture in the same global space using union.
Let me provide an example of the 2 structures that I use in my application
struct test1
{
int x[3000];
float y[2000];
char z[3000];
int a1[3000];
float a2[2000];
char b1[3000];
float c12[5000]; This member is not in test2
.
.
.
};
struct test2
{
int x[4000]; //Same member as in test1 with size increased
float y[1000]; //Same member as in test1 with size decreased
char z[5000]; //Same member as in test1 with size increased
int a1[2500]; //Same member as in test1 with size decreased
float a2[1000];//Same member as in test1 with size decreased
char b1[3000];//Same member as in test1
float abc[5000]; //Newly added in this structure only
.
.
.
};
|
|
|
|
|
|
Seriously it's trivial .. 6 lines of code as combined struct under your other 2 definitions
struct combined_test {
union {
struct test1 test1;
struct test2 test2;
};
}; Read the link he gave you or look up unionized structures
So that is an anonymous union.. AKA struct test1 and test2 occupy the same space no extra name needed.
So if you create a combined struct
struct combined_test lets_use_it;
lets_use_it.test1.z[100] = 10;
lets_use_it.test2.z[100] = 10;
lets_use_it.test1.c12[23] = 10; Where it fills in will respect the position in memory layout of test1.z[100] vs test2.z[100]
Now for your pointer it behaves like a pointer to both structs .. again it's UNIONIZED
struct combined_test* p = (struct combined_test*) malloc(sizeof(struct combined_test));
p->test2.z[100] = 32;
p->test1.z[100] = 55; No rocket science to it and make a sample and debug it if you need to check things.
In vino veritas
modified 15-Jun-17 14:23pm.
|
|
|
|
|
Thanks a lot. You have answered and explained what I had asked for. But I have a few hurdles to implement it.
I already have created the MFC application with a single structure defined in it. The global variable pointer for this structure struct1 is created and used through out the application.
As I had already said this MFC application invokes a console application at a time based on the user selection. There are many nearly some 1000 console applications which already are working. The MFC application creates a shared memory using CreateFileMapping and assigns the structure struct1 pointer to MapViewOfFile. The console application shares the same memory using the same struct1. So the same pointer name is used in both the MFC and all the console applications at many places.
Now my requirement is I have to increase the size and add some of the members in the struct1 to create struct2 for some of the console applications. So Now there will be some console applications that have struct1 and others have struct2. But the MFC application is a common application which invokes any particular console applications based on the selection. But there will be one mfc application and console application running at a time and sharing the memory. So If the MFC application invokes console application of type1 it should create a memory for struct1 and it creates memory for struct2 for console application of type2. The MFC application knows the type of console application at runtime and the pointer to be changed to point to either struct1 or struct2. And the pointer is already used in many many places in various console applications.
Is there a way in the mfc application to redefine the global pointer at runtime to make it point to struct1 or struct2 based on the console application type.
Eg: test->a[1000] = 23; //This usage code cannot be changed since used in many places
Note: Only common member variables are used in the MFC application. Hence the above line in the example will work for struct1 as well as for struct2 as both contains the member variable 'a' of the same type
|
|
|
|
|
First let me say you are making a mountain out of a molehill ... "test->" is a dead easy string to pick off with a text auto-replace on. Would take me about 30sec to do on code throughout the project.
You could also do what a good programmer would do and get rid of the stupid global pointer and pass it into the functions on the local interface. You can keep it as test on the local interface but pass in lets_use_it.test1. You make your code better, safer and it is simply extending a few local interfaces. That is what I would actually do .. globals are evil
The question to ask yourself is why are you using the global pointer rather than having a pointer parameter on the functions that use the global?
That all said you could keep the pointer "as is" if you want by typecasting but it is frowned on
struct test1* test = lets_use_it.test1;
In vino veritas
modified 16-Jun-17 10:22am.
|
|
|
|
|
We have a console application in VS2008 in which we have defined a global variable for a structure. The members of the variable are used throughout the application in various functions.
Recently we have taken some of the functions out of the application to create a separate library and have included the library and the header file in the console application.
Now When I build the application and run it, the output and behavior of the whole application is correct and same as before. But when i try to set breakpoints and debug some of the functions in the console application to watch the values in the watch window, the structure variable shows empty in the value column. The global variable for the structure is also used in the library.
Please suggest a solution to view the values in the watch window
modified 12-Jun-17 7:41am.
|
|
|
|
|
Check the project settings and ensure that both the application and library are built in Debug mode.
|
|
|
|
|
Problem solved. One of the lib was in release mode. got it fixed. Thanks
modified 13-Jun-17 3:38am.
|
|
|
|
|
That should work and does on VS2015 and VS2107 so if it doesn't work on VS2008 it's a very old bug.
You can however easily hack around it, just make a local variable struct and copy the global struct to the local ... the watch window can't get that wrong and it's one single line of code
Other alternative is to try the later compilers, they are free and easy to download and try.
In vino veritas
modified 13-Jun-17 3:04am.
|
|
|
|
|
Hey all,
When you save a webpage, eg from firefox "Web page, complete", it saves an html file and a folder containing its resources. No problem. But the tricky bit is, you move/copy/delete the html file the resource folder does the same.
How do they do that!?? I'm guessing there is some shell extension, but the only thing close I find in MSDN is ICopyHook, which seems more like a proceed/abort confirmation.
Thoughts?
(and dare I ask...) Examples?
|
|
|
|
|
It is a Windows shell feature called Connected Files[^] and applies only to HTML files (*.htm, *.html).
If you want an application to use that feature it must use shell file operations (SHFileOperation function (Windows)[^], IFileOperation interface (Windows)[^] ) instead of Windows API file operations.
I don't know for sure how it is implemented but I guess that it just checks for the existance of matching directories for HTML files and vice versa for directories with the listed extension.
|
|
|
|
|
The HTML filename is used to create the associated directory, so they are connected by name.
|
|
|
|
|
Hello!I'm trying to disable a text box (named m_EarthPermeability) and I want to disable it if a certain value is in Combobox (named m_Layers which gets two values "1" and "2"). Both textbox and Combobox are on the same Dialog window. I have written the code below but the textbox is still in "use" after choosing value "2" in Combobox. Here is the code:
CInputView::CInputView()
: m_Layers(0)
, m_EarthPermeability(0)
void CInputView::OnLinefeaturesFeatures()
{
CInputDoc* pDoc = GetDocument();
CFeaturesDialog DialogWindow;
DialogWindow.m_DialogLayers = m_Layers;
DialogWindow.m_DialogEarthPermeability = m_EarthPermeability;
{
if (m_Layers == 2) {
GetDlgItem(IDC_Permeability)->EnableWindow(FALSE);
}
}
modified 8-Jun-17 5:33am.
|
|
|
|
|
To disable a control you have to call EnableWindow(FALSE) but in your code snippet you are passing TRUE .
I understand also that the text box is part of the dialog and not of your view. Then you have to use
if (m_Layers == 2) {
DialogWindow.GetDlgItem(IDC_Permeability)->EnableWindow(FALSE);
}
It is also not clear if the member variables of your dialog are controls (CEdit , CComboBox ) or values (CString , int ). Your code is correct for value types but not for control types (which is indicated by "a text box (named m_EarthPermeability)").
|
|
|
|
|
I changed the errors you mentioned but still didn't work. So I made some more changes concerning the combobox but didn't work either. Here is the code:
void CInputView::OnLinefeaturesFeatures()
{
CInputDoc* pDoc = GetDocument();
CFeaturesDialog DialogWindow;
CString buffer;
buffer.Format(L"%d", m_Layers);
DialogWindow.m_DialogLayers = buffer;
DialogWindow.m_DialogEarthPermeability2 = m_EarthPermeability;
if (m_Layers == 2) {
DialogWindow.GetDlgItem(IDC_EarthPermeability2)->EnableWindow(FALSE);
}
}
where m_DialogLayers is CString type and its control type is combobox. Variable m_Layers is int variable.
|
|
|
|
|
It can not work that way because the dialog is not shown so far. Before you can change the visibility of a dialog's control you must show the dialog using DoModal() (for a modal dialog) or Create() and ShowWindow() (for a modeless dialog).
But your general approach is wrong. You should put the code to disable the control into the dialog class. Do it there in OnInitDialog() for the initial display and into handlers upon changings (e.g. by handling the CBN_SELCHANGE notification code (Windows)[^] )
|
|
|
|
|
Could you please give me some more information on how to use CBN_SELCHANGE cause I am not very familiar with that. You mean to use it in OnInitDialog() ?I tried different cases but still didn't manage to make it work. Thank you in advance for your time and help!!
|
|
|
|
|
In your view you create an instance of the dialog, set the members for the control as already done and finally call DoModal() to show the dialog (I will not handle modeless dialogs here).
When having a modal dialog the default implementation of OnInitDialog() will call CWnd::UpdateData[^] to set the controls from the corresponding member variables. Override OnInitDialog() to do additional initialisation:
BOOL CFeaturesDialog::OnInitDialog()
{
BOOL bRet = CDialog::OnInitDialog();
if (m_DialogLayers == 2)
GetDlgItem(IDC_Permeability)->EnableWindow(FALSE);
return bRet;
}
If you want to enable/disable the control when the user changes the combo box selection, you have to add a corresponding handler. Open the dialog resource in the resource editor, right click on the combo box to open the context menu and select the option to add a handler. That will open a dialog that allows you to choose the notification. Select CBN_SELCHANGE and apply the settings. That will create a function declaration in the header file, a function body in the source file, and open the source file at the created function. See also Adding an MFC Message Handler[^]. You should become familiar with that because you have to use it frequently with MFC applications.
In your case get the pointer to the control and use that to get the index (untested):
CFeaturesDialog::OnCbnSelchange()
{
CComboBox *pCombo = (CComboBox*)GetDlgItem(IDC_LAYERS);
GetDlgItem(IDC_Permeability)->EnableWindow(pCombo->GetCurSel() != 2);
}
|
|
|
|
|
I saw here:
Flicker Free Drawing In MFC[^]
in MemDC source code a line:
CMemDC* operator->()
{
return this;
}
Sorry for this simple question: it was really necessary ?
If I have an already pointer to an CMemDC object, and I write pMemDC->, then is not the same thing like this operator didn't has been overloaded ?
Thank you for any clarifying !
|
|
|
|
|
It is the same if you already have a pointer. But that class is usually created as
CMemDC pDC(dc); where you don't have a pointer.
The reason for the overload is that the class is used instead of the CDC* which is passed to the drawing functions. So you can modify existing code for the CDC* by just replacing the variable name without changing the access operator from -> to . .
Using such is bad practice but has been used by MFC too. It makes sense for this special class but should be generally avoided.
|
|
|
|
|
|
I think I can help but I am struggling with the grammar and intent of your question. -> operator gives you access to the class. It is much like operator .
|
|
|
|
|
I was reading this article, and I'm trying to understand a point that the author is trying to make.
Bartek's coding blog: Smart pointers gotchas[^]
class Test
{
public:
Test():m_value(0) { std::cout << "Test::Test" << std::endl; }
~Test() { std::cout << "Test::~Test destructor" << std::endl; }
int m_value;
};
typedef std::auto_ptr<test> TestAutoPtr;
typedef std::unique_ptr<test> TestUniquePtr;
typedef std::shared_ptr<test> TestSharedPtr;
void doSomethig(TestAutoPtr myPtr) {
myPtr->m_value = 11;
}
void AutoPtrTest() {
TestAutoPtr myTest(new Test());
doSomethig(myTest);
myTest->m_value = 10;
}
The author says this will crash. It seems that when myTest is instantiated, there is an auto_ptr object that now exists as a member of myTest, pointing to a heap instantiation of Test. Then when doSomethig() is called the *value* of the pointer is passed (i.e., the address of that heap Test object), and a new auto_ptr object, myPtr, is created, with its value set to the address of that Test object. And then after doSomethig() finishes, myPtr is destroyed, but since it is an auto_ptr, that destruction will delete the object that has the address of its value (i.e., the Test object). So, when a dereference of the myTest object (i.e., an auto_ptr object) is attempted, the Test object is no longer there, and hence an error that is as per trying to dereference an uninitialized (or perhaps null?) pointer.
Is my explanation accurate?
|
|
|
|
|
Close but not quite the actual rule goes
An auto_ptr owns the thing/object that it holds a pointer to, and only one auto_ptr may own an object at a time. When you copy an auto_ptr, you automatically transfer ownership from the source auto_ptr to the target auto_ptr. After the copy, only the target auto_ptr owns the pointer and will delete it in due time, while the source is set back to a null state and can no longer be used to refer to the owned object.
The line
doSomething(myTest);
has an implicit copy because you passed in myTest so the ownership goes into doSomething (passing like that is called an auto_ptr sink operation) and myTest gets the null state as per the description. You can't use it afterwards because it got nulled so it's a guaranteed crash if you try to use the pointer.
If you want the auto-pointer back again you should have made doSomething a function returning an auto_ptr and passed it back out, try something like
TestAutoPtr doSomethig(TestAutoPtr myPtr) {
myPtr->m_value = 11;
return myPtr;
}
The higher level code becomes
void AutoPtrTest() {
TestAutoPtr myTest(new Test());
myTest = doSomethig(myTest);
myTest->m_value = 10;
}
It's just an ownership thing .. only one scope of code can own an autoptr. If you want it back again you need to pass it back otherwise it is assumed it is no longer in use and cleaned up.
The actual crash has nothing to do with the cleanup the null of the auto_ptr is automatic when it copied and it's that which causes the crash. You are attributing the crash to the cleanup which isn't the case. If you could somehow keep the autoptr inside doSomething alive say with multitask code you still couldn't use the original pointer because it's value will be null.
Just use the debugger put a breakpoint on doSomething and single step into it and look at what happens to the original pointer .. your toast from that point on with the original code because it will go to null
In vino veritas
modified 6-Jun-17 16:10pm.
|
|
|
|