|
The code you have shown above does not match the code you are using. If I change it to the following, then it produces the results that you see.
class CBaseClass
{
public:
virtual void Function() {
cout<<"\nBase Class.";
}
};
class CChildClass : CBaseClass
{
public:
void Function() {
cout<<"\nChild Class.";
}
};
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
The bug in your code is obvious. CPallini already gave you the correct code but I feel this is something that needs further clarification.
The bug is the following, and its a major bug in its current context:
CChildClass* pChild = (CChildClass*)pBase;
There are 2 kinds of static casts: downcast and upcast. If you are drawing the uml diagram of your class hierarchy then it looks like a tree with its root node (base class) at the top of the diagram. Down and upcast are named based on the direction of the cast in this tree so an upcast means that you cast a derived class to one of its base classes in the hierarchy, this type of cast is safe, you don't have to mark it explicitly in your code because the compiler does it automatically for you:
Derived * d = new Derived;
Base* b = d;
However downcasts are not only dangerous but they usually mean that you committed a design mistake. A base class can have a lot of derived classes and if you are casting a base class to one of its derived classes than its a bug if the actual object isn't an instance of the downcast type or its descendants. People often say that dowcasts defeat the whole purpose of polymorphism/late binding. Example:
class Base;
class A : public Base;
class B : public Base;
Base* b = new B;
A* p = (A*)b;
So why doesn't your code crash??? Because you were lucky and currently in your simple example the binary representation of instances created by the compiler for your base and derived classes are probably identical, they just differ in their vtable pointer but in any more complex situations it could easily crash.
OK, so when you have a complex hierarchy and you call a virtual function on a base class pointer then which method is executed??? It depends on which object have you actually created! (with new). Since in your example you created just a Base instance it would be magic to see executing the method of the derived class, and its just luck that using the pointer that you filled with your invalid downcast haven't crashed your program.
So based on what we have learned up until now you should only use upcasts that are done automatically for you by the compiler, for example:
CBaseClass* p = new CChildClass; p->Function();
Describing the same in other words:
You can always use a base class pointer to point to an object that was created by instantiating a class derived from the base class. This way if you call some virtual methods on the base class pointer then the methods of the actually instantiated class are called.
modified 24-Sep-12 14:17pm.
|
|
|
|
|
Veni, vidi, vici.
|
|
|
|
|
|
Good explanation about the perils of upcasting and downcasting and how in this simple example the downcasting worked, but that in a real world case, it would likely crash.
Chris Meech
I am Canadian. [heard in a local bar]
In theory there is no difference between theory and practice. In practice there is. [Yogi Berra]
posting about Crystal Reports here is like discussing gay marriage on a catholic church’s website.[Nishant Sivakumar]
|
|
|
|
|
|
+5. Great explanation. For me too, I've been reversing upcast and downcast terms, didn't think of the diagram. Saw the obvious error in his example though.
|
|
|
|
|
|
Regarding the upcast/downcast naming: A lot of coders exchange these names so when someone starts using them I always ask him to clarify how to interpret "his upcast" right at the start of the conversation. I also used them in reverse order for a long time until reading some uml docs that clarified it for me. For some reason thinking that upcast is casting up to a higher level smarter derived class seemed to be more logical for me.
|
|
|
|
|
Which is how I use "upcast", to a "bigger" container, the derived class. Of course, that's just a convenience notation. The real idea is
Cast Derived to Base - OK
Cast Base to Derived - Bad
|
|
|
|
|
Hi, have a good day
I am using Already built DLL , with callback function inside it :
After I execute this code my application freeze ( SomeCallback : read only once ) and freeze
I don't know what is wrong ?
DLL Define code ( DLL is open source ) :
typedef int __stdcall cbtype (char *what, Number int1, Number int2, char *str);
extern "C" int __cdecl FreeArcExtract (cbtype *callback, ...);
My Code :
#include <cstdlib>
#include <iostream>
#include "windows.h"
using namespace std;
typedef bool (*cbtype) (char *what, int, int, char *str);
bool SomeCallback( char *c1 , int i1 , int i2, char *c2)
{
printf("%s\r\n" , c1);
printf("%d\r\n" , i1);
printf("%d\r\n" , i2);
printf("%s\r\n" , c2);
return true;
}
void ArcExtract ()
{
HINSTANCE GetProcDLL = LoadLibrary("unarc.dll");
FARPROC GetProcessID = GetProcAddress(
HMODULE (GetProcDLL), "FreeArcExtract");
typedef int (__cdecl * CallingFun)(cbtype, LPCTSTR , LPCTSTR, LPCTSTR , LPCTSTR,LPCTSTR , LPCTSTR,LPCTSTR , LPCTSTR,LPCTSTR , LPCTSTR);
CallingFun FreeArcExtract;
FreeArcExtract = CallingFun(GetProcessID);
FreeArcExtract((cbtype)SomeCallback,
"l", "--", "d:\\test.arc", "", "", "", "", "", "", "");
FreeLibrary(GetProcDLL);
}
int main(int argc, char *argv[])
{
ArcExtract ();
return EXIT_SUCCESS;
}
I think the error are in the call back function
I write the same code on C# and it's work like charming.
with same dll , and the same d:\test.arc
C# Code :
class ArcArchive
{
public delegate bool unarcCallBack(string what, int param1, int param2, string text2);
[DllImport("unarc.dll")]
public static extern int FreeArcExtract(unarcCallBack callback,
string cmd1, string cmd2, string cmd3, string cmd4, string cmd5, string cmd6, string cmd7, string cmd8, string cmd9, string cmd10);
}
static void Main(string[] args)
{
ArcArchive.unarcCallBack ArcCallBack = new ArcArchive.unarcCallBack(CallBackFunction);
ArcArchive.FreeArcExtract(ArcCallBack,
"l", "--", "d:\\test.arc", "", "", "", "", "", "", "");
}
static bool CallBackFunction(string what, int param1, int param2, string t2)
{
Console.WriteLine(what);
Console.WriteLine(param1);
Console.WriteLine(param2);
Console.WriteLine(t2);
return true;
}
please is there is anyway to write callback function in c++ ? or is my c++ code had some logical errors.
Thank you
|
|
|
|
|
You have mixed up a lot, specially with typedef and function pointer definition and usage. To understand function pointer definition clearly read about Function Pointer[^]. Also look at wiki link[^] to learn about typedef in detail.
To solve your problem
1. write include of windows.h as
#include <windows.h>
and it has nothing to do with your problem
2. If you have the .lib file then it is great just include the header file as below:
#include "the_header_file.h"
and also include the library file with your project.
if you dont have then follow the code it might help:
#include <cstdlib>
#include <iostream>
#include <windows.h>
using namespace std;
typedef bool (*cbtype) (char *what, int, int, char *str);
bool SomeCallback( char *c1 , int i1 , int i2, char *c2)
{
printf("%s\r\n" , c1);
printf("%d\r\n" , i1);
printf("%d\r\n" , i2);
printf("%s\r\n" , c2);
return true;
}
void ArcExtract ()
{
HINSTANCE GetProcDLL = LoadLibrary("unarc.dll");
if(GetProcDLL==NULL)
{
}
typedef int (__cdecl * CallingFun)(cbtype, ...);
CallingFun FreeArcExtract;
FreeArcExtract =(CallingFun) GetProcAddress(HMODULE (GetProcDLL), "FreeArcExtract");
if(FreeArcExtract==NULL)
{
}
FreeArcExtract((cbtype)SomeCallback,
"l", "--", "d:\\test.arc", "", "", "", "", "", "", "");
FreeLibrary(GetProcDLL);
}
int main(int argc, char *argv[])
{
ArcExtract ();
return EXIT_SUCCESS;
}
I wish I could believe there is an after life.
|
|
|
|
|
Thank you Sir, I have Solved the problem
Here is the Fixed Code
#include <cstdlib>
#include <iostream>
#include <windows.h>
using namespace std;
typedef int __stdcall cbtype (char *what, int int1, int int2, char *str);
int __stdcall somecallback (char *what, int int1, int int2, char *str)
{
cout << what << endl;
cout << int1 << endl;
cout << int2 << endl;
cout << str << endl;
}
void ArcExtract ()
{
HINSTANCE GetProcDLL = LoadLibrary("unarc.dll");
FARPROC GetProcessID = GetProcAddress(HMODULE(GetProcDLL), "FreeArcExtract");
typedef int (__stdcall * CallingFun)(cbtype, ...);
CallingFun FreeArcExtract;
FreeArcExtract = CallingFun(GetProcessID);
FreeArcExtract(somecallback,"l", "--", "d:\\test.arc", "", "", "", "", "", "", "");
FreeLibrary(GetProcDLL);
}
int main(int argc, char *argv[])
{
ArcExtract ();
system("pause");
return EXIT_SUCCESS;
}
|
|
|
|
|
Can anybody tell me why there are TWO implementations for the MFC message map? I think the non _AFXDLL version will be OK in both the static library and dynamic library.
#ifdef _AFXDLL
#define DECLARE_MESSAGE_MAP() \
private: \
static const AFX_MSGMAP_ENTRY _messageEntries[]; \
protected: \
static AFX_DATA const AFX_MSGMAP messageMap; \
static const AFX_MSGMAP* PASCAL _GetBaseMessageMap(); \
virtual const AFX_MSGMAP* GetMessageMap() const; \
#else
#define DECLARE_MESSAGE_MAP() \
private: \
static const AFX_MSGMAP_ENTRY _messageEntries[]; \
protected: \
static AFX_DATA const AFX_MSGMAP messageMap; \
virtual const AFX_MSGMAP* GetMessageMap() const; \
#endif
|
|
|
|
|
I have never noticed this but partly the answer is obvious if you take a look at the name of the defined identifier after the #ifdef, its _AFXDLL. The MFC libraries can be linked statically into your executable/DLL or you can choose to be linked dynamically so that your program will depend on the existence of an mfc library dll where your program is used. It seems that they needed different macros to wire together their system in these 2 different cases but this is a tiny implementation detail inside MFC you dont have to be aware of. In general you often have to handle some problems specially when you put part of your code into a DLL, but its not important what their reason was for creating those 2 different defines because they provide the same interface for you.
|
|
|
|
|
|
|
I noticed that the latest MFC messageMap has a new implementation, it is not ambiguous anymore! there is no _AFXDLL version.
|
|
|
|
|
pasztorpisti has gven you some good advice and I would just add to it, to ensure that you do not mix MFC within an application. By that, I mean if you are building a DLL for an application and that application uses MFC linked statically, then ensure that your DLL has MFC linked statically as well. The converse is also true. If the application links MFC dynamically, then ensure that you're DLL links MFC dynamically.
Chris Meech
I am Canadian. [heard in a local bar]
In theory there is no difference between theory and practice. In practice there is. [Yogi Berra]
posting about Crystal Reports here is like discussing gay marriage on a catholic church’s website.[Nishant Sivakumar]
|
|
|
|
|
Agree, very useful info to help avoiding some disasters.
|
|
|
|
|
Thanks.
Chris Meech
I am Canadian. [heard in a local bar]
In theory there is no difference between theory and practice. In practice there is. [Yogi Berra]
posting about Crystal Reports here is like discussing gay marriage on a catholic church’s website.[Nishant Sivakumar]
|
|
|
|
|
how to watch the code of the software of th ImageStone?
why I cannot see the code of some function? ,
for example how the see the function code of colour level,
|
|
|
|
|
If you have the source code then you need to build it in Debug mode. If you do not have the source code then see here[^].
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Can someone tell me why C++ and C programming languages are used than any other programming languages, what can these languages do that others can't. I do know that C can create drivers or system files, which is very important when you become serious about your projects. But why is the industry still use it? And will C or C++ ever die, even though it's a non-stop updating language everyday, and what other languages update just like C/C++.
EDIT:
While also asking this question, will C++/CLI take over or kill out Standard/Win32 C++?
Cause I'm on a website called Codejock Software, looking for a ribbon control to work for Standard/Win32 C++ only, and I can't find it. Most of the controls are only made for C++/CLI.
Simple Thanks and Regards,
Brandon T. H.
Programming in C and C++ now, now developing applications, services and drivers (and maybe some kernel modules...psst kernel-mode drivers...psst).
Many of life's failures are people who did not realize how close they were to success when they gave up. - Thomas Edison
modified 3-Oct-12 14:46pm.
|
|
|
|
|
Brandon T. H. wrote: what can these languages do that others can't.
Directly access the hardware, directly manage memory, and create high performance code.
(As opposed to managed languages)
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|