|
I'm sorry, my answer was a quick guess. That's why I put a question mark after it.
Truth is I'm not sure.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Hi,
In my MFC project, I get crash as follows:
1. i call MyCreate() then MyUnCreate()
2. calling MyCreate() the second time, causes crash at AfxRegisterWndClass below.
sudo code provided:
CMyCwndSub is derived from CWnd.
in another file:
CMyCwndSub *p;
void MyCreate()
{
p->new CMyCwndSub;
CString m = AfxRegisterWndClass(0); p->CreateEx(0, m, -T"MyWndWin",0,0,0,0,0,NULL,0);
.
.
.
}
void MyUnCreate()
{
delete p;
p = NULL;
}
|
|
|
|
|
|
would this work?.
void MyUnCreate()
{
::UnregisterClass(_T("MyWndWin"), AfxGetInstanceHndle());
delete p;
p = NULL;
}
|
|
|
|
|
Didn't you test it?
Also you must pass to UnregisterClass the className returned by AfxRegisterWndClass(...), not the caption of your window!
modified 13-Jun-24 11:25am.
|
|
|
|
|
I did the following and still crashed. Maybe the AfxRegisterWndClass is set to release class automatically at the end when library exits. ?
void MyUnCreate()
{
::UnregisterClass(ClassName, AfxGetInstanceHandle());
delete p;
p = NULL;
}
|
|
|
|
|
etechX2 wrote: Maybe the AfxRegisterWndClass is set to release class automatically at the end when library exits. ?
1. Please read the Microsoft documentation about AfxRegisterWndClass;
2. Why are you trying to unregister and then reregister already registered Class? just save its name and then use it again!
|
|
|
|
|
Hi Guys,
I have recently came across one scenario where I have to insert a user defined key in a c++ map. that class looks like this
class key
{
int id;
string name;
};
map is like map<key,int>
I'll overload "operator<" function and will sort out based on "id" which will works fine, but the condition is like, if there are 2 entry with same ID but with a different name, for ex. {"50", Jack} and {"50", John}
As both the values have SAME ID and different name, map should make an entry for both.
Only in the case of combination of same ID and same name, it shouldn't allow the entry.
bool operator<(key& temp)
{
if(id < temp.id)
{
return true;
}
if( id == temp.id)
return name < temp.name;
}
its not working properly, its overriding the last entry if same ID is there.
Please help me out
-- modified 10-Jun-24 15:02pm.
|
|
|
|
|
Try std::multimap. It does exactly what you want.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Disclaimer: What I'm about to talk about is C++ implementation details. C++ compilers aren't *necessarily* implemented the way I describe in theory, but in practice they virtually all are - at least the major ones, AFAIK.
C++ is very "lexical" in how it works.
The bones of the OOP, method overloading, and template instantiations are implemented in part through name mangling, which is fundamentally lexical vs having a different, say, integer or binary key for each of the above.
The template instantiations work like a mail merge, but with "smart" template parameters (by smart I mean, not simply lexical but type aware, compiler resolved). The actual template code is basically search and replaced, but template resolution is "smart" (similar to how i used the word above) in that it can resolve recursively and stuff, so it's a bit more complicated than strict search replace, but it's close.
C++ in many ways (but not all ways) is C with syntactic sugar.
C++ OOP isn't special. It's basically C with a combination of name mangling, and hiding the first (implicit) this argument
consider the following
#include <stdio.h>
class foo {
int m_bar;
public:
foo() : m_bar(0) {
}
int bar() const { return this->m_bar; }
void bar( int value) { this->m_bar = value; }
};
typedef struct _foo_c {
int bar;
} foo_c_t;
void foo_foo_foo_c_t(foo_c_t* handle) {
handle->bar = 0;
}
int foo_bar_foo_c_t(foo_c_t* handle) {
return handle->bar;
}
void foo_bar_foo_c_t_int(foo_c_t* handle, int value) {
handle->bar = value;
}
int main(int argc, char** argv) {
foo foo_cpp;
foo_cpp.bar(42);
foo_c_t foo_c;
foo_foo_foo_c_t(&foo_c);
foo_bar_foo_c_t_int(&foo_c,42);
printf("foo_cpp: %d, foo_c: %d\n",foo_cpp.bar(),foo_bar_foo_c_t(&foo_c));
return 0;
}
That's C++ and its rough equivalent as C code, and the C is similar to how the C++ resolves internally.
I feel like understanding that helped me greatly understand C++.
I'm wondering if any other C++ developers out there had a similar epiphany about the language that helped them understand it better, and what it was.
Part of it is I was thinking of compiling an article about this, but the above isn't enough by itself.
I'm hoping to add more content, but maybe some of you who have had similar epiphanies about the language could inspire more content along this vein. If so, please put it in a reply. Thanks!
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
honey the codewitch wrote: C++ in many ways (but not all ways) is C with syntactic sugar.
One might argue that C is just assembler with syntactic sugar too.
I think you could make the same argument about any of the C Family of languages: C, C++, Objective C, Java, C# etc. Perhaps even Go and Rust?
And, of course, we can't forget that Bjarne Stroustrup's original work on C++ (C with classes) was implemented with Cfront - Wikipedia, which converted C++ code to plain C.
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
No. In C# a class is first class, binary structured as a class to the CLI, with metadata, etc.
In C++, a class is little more than what I demonstrated with code above - a bunch of renamed methods with a hidden this parameter.
I guess I wasn't clear. I even produced code to try to make it clear. Meh.
But I guess yeah - Cfront existed. C++ is C with syntactic sugar.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
modified 8-Jun-24 9:46am.
|
|
|
|
|
Cfront (I had forgotten that name!) taught me "everything" about OO. I guess I should say "all the fundamentals" - OO has developed since then.
I had been OO programming since 1979, student exercises in Simula, but our Compiler Construction course did not address OO at all. (Maybe later editions of the dragon book did, but not the current edition when we were students.) So, when we got a chance to see in cleartext how a compiler realized OO mechanisms, it was like a revelation to us.
My memory and calendar suggest that we had access to the C++ compiler earlier than 1983, the official release date of Cfront - maybe it was in 1982. It wasn't uncommon for professors and students swimming across the pond to return with all sorts of new and fancy software discretely hidden in their briefcases. Maybe the 'Cfront' name wasn't assigned to it, and that is why I don't remember the name.
Religious freedom is the freedom to say that two plus two make five.
|
|
|
|
|
honey the codewitch wrote: I'm wondering if any other C++ developers out there had a similar epiphany about the language that helped them understand it better, and what it was.
Certainly that wasn't the case for me.
I didn't have a problem understanding the language. I had a problem thinking about problems that lead to Object Oriented designs. Rather than structured designs.
honey the codewitch wrote: but with "smart" template parameters (by smart I mean, not simply lexical but type aware, compiler resolved).
I solve enterprise problems. And I have been doing that for a very long time. Language syntax sugar is often just gets in the way of large scale solutions which must be maintained for decades. A company that is going to be successful is going to hire a large number of developers and that means they will tend towards the average and not the above average. And they will have specific and limited skill sets that they have learned, even senior developers. Relying on esoteric language features lead to nothing but confusion and higher maintenance costs.
|
|
|
|
|
Ummm, templates are not an esoteric language feature. The Standard Template Library is based around them.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
Using a library and writing one are two different things.
I have written an XML parser. I have also used XML libraries. I would much rather find and use an existing.
I have also written templates (with care.) But that doesn't mean that I want all developers to write them. Not in enterprise systems.
|
|
|
|
|
Fair enough. I do embedded, and I write libraries, so I use templates often enough.
It's particularly useful when doing hardware mapping of a C++ based device controller. The pins for example, can be set at compile time because they're soldered onto the board, and IMO it's much cleaner than a #define.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
honey the codewitch wrote: hardware mapping of a C++ based device controller.
Sounds good.
But I don't want some mid-level developer that just discovered templates and databases to decide that he/she is going to improve the world by creating templates that encapsulate everything in the database layer.
|
|
|
|
|
Disclaimer: The following is intended to run in embedded environments that may not have a compliant STL if they have the STL at all. Some of this code could be replaced on systems with The STL to use std:: functionality.
Anyway, it's code I wrote, but it's not my code that really impresses me about this, but rather the C++ compiler.
static_assert(pixel_type::template equals<gfx::rgb_pixel<16>>::value,
"this code needs to be ported for your display format");
That's a compile time check to determine if a pixel format is exactly the same as the specified pixel format.
Not impressed yet?
Those pixel formats are arbitrarily defined:
template<size_t BitDepth>
using rgb_pixel = pixel<
channel_traits<channel_name::R,(BitDepth/3)>,
channel_traits<channel_name::G,((BitDepth/3)+(BitDepth%3))>,
channel_traits<channel_name::B,(BitDepth/3)>
>;
template<size_t BitDepth>
using rgba_pixel = pixel<
channel_traits<channel_name::R,(BitDepth/4)>,
channel_traits<channel_name::G,((BitDepth/4)+(BitDepth%4))>,
channel_traits<channel_name::B,(BitDepth/4)>,
channel_traits<channel_name::A,(BitDepth/4),0,(1<<(BitDepth/4))-1,(1<<(BitDepth/4))-1>
>;
template<size_t BitDepth>
using gsc_pixel = pixel<
channel_traits<channel_name::L,BitDepth>
>;
template<size_t BitDepth>
using yuv_pixel = pixel<
channel_traits<channel_name::Y,((BitDepth/3)+(BitDepth%3))>,
channel_traits<channel_name::U,(BitDepth/3)>,
channel_traits<channel_name::V,(BitDepth/3)>
>;
And furthermore
template<
typename Name,
size_t BitDepth,
bits::uintx<bits::get_word_size(BitDepth)> Min=0,
#if HTCW_MAX_WORD >= 64
bits::uintx<bits::get_word_size(BitDepth)> Max= ((BitDepth==64)?0xFFFFFFFFFFFFFFFF:((1<<BitDepth)-1)),
#else
bits::uintx<bits::get_word_size(BitDepth)> Max= ((BitDepth==32)?0xFFFFFFFF:((1<<BitDepth)-1)),
#endif
bits::uintx<bits::get_word_size(BitDepth)> Default = Min,
bits::uintx<bits::get_word_size(BitDepth)> Scale = Max
>
struct channel_traits {
using type = channel_traits<Name,BitDepth,Min,Max,Scale>;
using name_type = Name;
using int_type = bits::uintx<bits::get_word_size(BitDepth)>;
using real_type = bits::realx<16<=BitDepth?HTCW_MAX_WORD:32>;
constexpr static const size_t bit_depth = BitDepth;
constexpr static const int_type min = Min;
constexpr static const int_type max = Max;
constexpr static const int_type default_ = Default;
constexpr static const int_type scale = Scale;
constexpr static const real_type scaler = 1/(real_type)Scale;
constexpr static const int_type int_mask = ~int_type(0);
constexpr static const int_type mask = bits::mask<BitDepth>::right;
static_assert(BitDepth>0,"Bit depth must be greater than 0");
static_assert(BitDepth<=64,"Bit depth must be less than or equal to 64");
static_assert(Min<=Max,"Min must be less than or equal to Max");
static_assert(Default>=Min,"Default must be greater than or equal to the minimum value");
static_assert(Default<=Max,"Default must be less than or equal to the maximum value");
#if HTCW_MAX_WORD >= 64
static_assert(Max<=((BitDepth==64)?0xFFFFFFFFFFFFFFFF:((1<<BitDepth)-1)),"Max is greater than the maximum allowable value");
#else
static_assert(Max<=((BitDepth==32)?0xFFFFFFFF:((1<<BitDepth)-1)),"Max is greater than the maximum allowable value");
#endif
static_assert(Scale>0,"Scale must not be zero");
};
I don't know of any other language that allows this kind of compile time expressiveness. I wish they did. Sometimes it feels like I'm "in dialogue" with the compiler rather than with the generated/runtime code as with most languages.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
I have one more question.
I will try my best to describe the issue and hoping the discussion does not get centered on terminology and RTFM as in the past.
That is not an instruction on how to reply, just a polite request to get real and skip opinions.
( And if you think me saying this is rude...
I am just trying to get of the dime and writing it as politely as I know)
I did have resolved the syntax of "passing the class" , however now I am stuck with WHERE the class should be declared.
In layman terms - the calling object passes a class pointer to the function, which happens to be my own created library. I expect the library function to PROCESS the passed class...
And that is where I am not sure if I have to define / declare the SAME class again - this time in the library.
I did test this using / passing SINGLE variable pointer and it worked OK.
I am not sure what to do when the entire class is passed.
I do not think dupicating the class definition is vise.
(Maybe it needs to be declared as global to the project ?)
Any theoretical help , answer, would be appreciated, I can manage the code...
Cheers
class BT_UTILITY_LIBRARY_EXPORT BT_Utility_Library
{
public:
class Test;
QString DEBUG_Process(void);
QString DEBUG_Process(int *);
QString DEBUG_Process(class Test *);
QString DEBUG_Process_Class(class Test *);
QString REG_EXP_Process(void);
class Test
{
public:
int a;
QString text;
}TestPointer;
|
|
|
|
|
It sounds like you're trying to implement in interface. Typically you'd do this by determining what behaviors an object might require and write a base (abstract) class that captures that. You then write your library functions so that they only make use of the public functions in the base class. The derived objects implement the methods in the base class in a way that makes sense for the derived object. There's plenty of examples out there, just google for "C++ interface" or "C++ abstract class". Almost any of which will give you better examples that I can come up with.
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
Could somebody please help me with solving this?
note: passing argument
to parameter 'Agrument' here
QString DEBUG_Process_Class(class REG_EXP_Class *Agrument );
I just cannot find any RTFM to "passing class pointer" to function ,
and I have no issues passing int * to a function.
Thanks for the reply.
I am not sure HOW to change to the "abstract class".
I have been struggling with Qt implementation of anything related to inheritance.
Anyway,
I did implemented the "supporting " class as a global variable.
I have not done "globals" for years and it was an OF memory exercise...
pREG_EXP_Class = new REG_EXP_Class;
pREG_EXP_Class->a = 10;
pREG_EXP_Class->text = "test text ";
pBTUL->DEBUG_Process_Class(pREG_EXP_Class);
All is working , until I did try to actually pass the class pointer...
Then I get this error and have no ideas where is my coding error.
/mnt/A_BT_DEC10/A_MAY_9_MAY31_CLEAN_BACKUP/A_APR9_MAR7_MAR19_CLEAN/A_BT_LIBRARY/A_DEC17_Bluetoothctl_Dialog_V1/mainwindow_bluewtoothctl_dialog.cpp:8911:
error: cannot initialize a parameter of type 'class REG_EXP_Class *' with an lvalue of type 'REG_EXP_Class *'
mainwindow_bluewtoothctl_dialog.cpp:8911:28: error: cannot initialize a parameter of type 'class REG_EXP_Class *' with an lvalue of type 'REG_EXP_Class *'
pBTUL->DEBUG_Process_Class(pREG_EXP_Class);
^~~~~~~~~~~~~~
../A_DEC17_BT_Utility_Library/bt_utility_library.h:59:54: note: passing argument
to parameter 'Agrument' here
QString DEBUG_Process_Class(class REG_EXP_Class *Agrument );
^
I could use some advise how to correctly pass the class pointer, this
"try this ... try that" is tedious.
and before I get " get a book..." I have no idea under what subject to look for...
" passing paramater to argument " ???
modified 3-Jun-24 10:29am.
|
|
|
|
|
QString DEBUG_Process_Class(class REG_EXP_Class *Agrument );
Remove the word class from the parameter in your function definition. The type REG_EXP_Class* is complete, it tells the compiler that Agrument is a pointer to an object of the REG_EXP_Class class. I would also suggest you remove the word Class from your class names, as it is redundant.
|
|
|
|
|
I explained what you should do to correct this in my previous reply. Passing a class pointer or reference is just the same as passing any other type. So a simple example:
class Foo
{
private :
int bar;
public:
Foo(int i) : bar(i) {} int getBar() {return bar; } };
int MyFunc(Foo* param)
{
int rc = param->getBar(); return rc * 2; }
int main
{
Foo* pFoo = new Foo(4); int ans = MyFunc(pFoo); cout << "result: " << ans << endl;
return 0;
}
And all of that, and more, is fully explained in any C++ reference, either online or in printed copy.
|
|
|
|
|
I am trying to improve my C++ skills and could use some advice.
I am using event driven tool - I am not allowed to say the name here -
and my basic question is
if I create an instance of a class which uses a library
should the library by instantiated in class constructor
as a common to all class methods variable
or
be instantiated in each method ( as a local method variable ) as needed ?
Process speed is immaterial, my question is about how is
memory allocated / de-allocated ( managed by C++) during the events.
|
|
|
|
|