|
Stuart Dootson wrote: Full stop. No argument
I'm not satisfied with this answer. I need to know why. So if it is theoretically impossible to instantiate an abstract class, my aim is to understand how the compiler is able to do that.
OK I know that "instantiating an abstract class" is moral issue ( ) ;
But my aim is not to break that moral barrier in my programming life, rather understand how does the compiler ensure that that barrier is not broken.
Just posting the question before I'll go and see the source code of a C++ compiler, in the aim that may be there is an answer.
|
|
|
|
|
hINTModuleState wrote: OK I know that "instantiating an abstract class" is moral issue
Is not a moral issue, it is a explicitely forbidden by the language.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
I used the expression "moral issue" in order to qualify an act that is against the rules of design.
instantiating an abstract class is explicitly forbidden by the langage, because the design rule says
that we can only instantiate derives of the abstract class. This is the explicit statement, but what about the compiler implementation ?
|
|
|
|
|
If the target is just fooling the compiler, then your (im my opinion, ta least) question is pointless.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
hINTModuleState wrote: Just posting the question before I'll go and see the source code of a C++ compiler, in the aim that may be there is an answer
Go on then...I think you may find the source of a C++ compiler less than straight forward.
hINTModuleState wrote: I need to know why
It's because you have undefined method pointers in the classes vtable (the methods you declared abstract have no definition, so cannot be referenced). Thus, the class is (in terms of instantiation) not fully defined, so creating an object of that type is erroneous.
|
|
|
|
|
Stuart Dootson wrote: It's because you have undefined method pointers in the classes vtable
I know that I have a vtable with empty case for the undefined virtual function..but do we know how and when the compiler checks that vtable ?
|
|
|
|
|
hINTModuleState wrote: do we know how and when the compiler checks that vtable ?
yes.
it does not.
it generates the data that will go there, if any.
|
|
|
|
|
The compiler doesn't check the vtable - it creates it. That's why the compiler won't let you instantiate an abstract class - by doing that, it can guarantee you don't try to call an undefined method.
|
|
|
|
|
Here's[^] a nice article explaining abstract classes and how a pure virtual method can be called in obscure circumstances.
|
|
|
|
|
thank you for that valuable link.
|
|
|
|
|
hINTModuleState wrote: I'll go and see the source code of a C++ compiler
great idea. When you're through, please provide an abstract, maybe an article would be nice. So we all can learn new things.
|
|
|
|
|
Here's how you can do it.
class A
{
public :
A(){}
~A(){}
virtual void do() = 0;
};
void main()
{
A* pA = (A*)malloc(sizeof(A));
pA->A::A();
}
«_Superman_»
|
|
|
|
|
«_Superman_» wrote: void main(){ A* pA = (A*)malloc(sizeof(A)); pA->A::A();}
You can’t allocate memory for Class through C malloc, because it just allocate the memory, but will not do any class object initialisation task like call for constructor/destructor.
Problem with malloc is now resolved in STL std::malloc, which provide support for allocating memory to class object and do starting and cleanup work
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow Never mind - my own stupidity is the source of every "problem" - Mixture
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You
|
|
|
|
|
ThatsAlok ou can’t allocate memory for Class through C malloc, because it just allocate the memory, but will not do any class object initialisation task like call for constructor/destructor
That's why he's called the constructor on the malloc ed block of memory - to initialise the object.
Does it work...yes. Should you do it...hell, no.
|
|
|
|
|
The two lines in the main function is exactly was the new operator does in Windows.
«_Superman_»
|
|
|
|
|
I added a data member to class A, then a concrete memeber to it that renders the content of that data member. In the contructor of A I initialized that data member with a certain value.
Finally in the main bloc I tried to make a call to the concrete member, it's working.
class A
{
public :
A(){myName=_T("outlaw class"}
~A(){}
virtual void do() = 0;
CString myName;
void concreteMember(){AfxMessageBox(myName);}
};
void main()
{
A* pA = (A*)malloc(sizeof(A));
pA->A::A();
pA->concreteMember();
}
I think that thanks to your trick, memory for the object is passively created then constructor called, bypassing the vtable creation and checking.
|
|
|
|
|
Nooo - the vtable is there. Consider this code:
#include <stdlib.h>
#include <stdio.h>
class Base
{
public:
virtual void do_it2() { printf("Base::do_it2\n"); }
};
class A : public Base
{
public :
A(){}
~A(){}
virtual void do_it() = 0;
virtual void do_it2() { printf("A::do_it2\n"); }
int a;
};
void aa(Base* pBase)
{
pBase->do_it2();
}
void main()
{
A* pA = (A*)malloc(sizeof(A));
pA->A::A();
aa(pA);
pA->do_it();
}
This will print "A::do_it2" - calling A::do_it2 through A's vtable!!! - before throwing a pure virtual function call exception as I'm calling the pure virtual function.
As I said before - there are NO (repeat NO) run-time checks performed on the vtable. C++ is quite happy to let you (metaphorically) shoot yourself in the foot if you really try to.
What Mr Superman's trick is bypassing is the compile-time checks that prevent you from instantiating an abstract class. That's the C++ philosophy - try to stop you compiling erronous code, but if you do, then you're on your own. There are no standard defined runtime checks to help you out...
modified on Tuesday, January 20, 2009 12:04 PM
|
|
|
|
|
As reported in previous threads, I had to remove all use of MFC from all my projects. This is supposed to increase portability. So I replaced all CStrings, CLists, Containers, etc.
It all compiles nicely now, but here is the latest problem - it won't build
error LNK2001: unresolved external symbol ___argv
error LNK2001: unresolved external symbol ___argc
In despair I recreated all my projects under VisualStudio8 with following properties:
console project Application exe
Use Standard Windows Libraries
Use Multi-Byte character set
When I recreated the projects it made new mains which look like this:
int _tmain(int ___argc, _TCHAR* ___argv[])
{
// here my bits
char *configfile;
if ( ___argc == 2 )
{
configfile = ___argv[1];
}
return 0;
}
And it won't link. So has anyone an idea what I am doing wrong?
-------------
Bibo ergo sum
|
|
|
|
|
__argc and __argv are defined in the C runtime library - make sure you're linking with one of the variants of the CRT.
Your problem is probably related to this Microsoft Knowledgebase article[^], although your situation doesn't match exactly.
|
|
|
|
|
That was it! I had to change the C run-time library from debug multithreaded DLL to debug multithreaded.
-------------
Bibo ergo sum
|
|
|
|
|
Dear All,
I have created a MFC DLL in VS 2005. I have included this dll (dll and lib) in the VS 2003. The project compiled and running well. But, when I run the exe in another system (XP with SP3) without VS then the exe throws an error saying that "Application not correctly initialized".
I dont know the reason of this problem. Please help me...
Regards,
Bhanu
|
|
|
|
|
You will need to download and install the vc redistributable package on the target computer. You can download it from here[^]. If you have the vc2005 service pack 1 installed, you should download the version for service pack 1 (see the links at the bottom of the page).
When executing this on the target machine, it will install the C-runtime libraries and MFC libraries.
Another option would be to statically link to the C-runtime library and MFC libraries.
|
|
|
|
|
Dear Moonen,
Thank you so much for your reply.
Installing vcredist_x86.exe solves the problem, but I want my dll to be self sufficient irrespective
of the versions.
I created a MFC DLL as "Regular DLL with MFC statically linked". The dll is created properly, but if I include in my MFC dialog based project I got linker error (error LNK2019: unresolved external symbol). Please help me...
Many thanks in advance.
Bhanu
|
|
|
|
|
bhanu_8509 wrote: The dll is created properly, but if I include in my MFC dialog based project I got linker error (error LNK2019: unresolved external symbol)
What is the exact error message ?
Your MFC application also needs to statically link to the MFC.
|
|
|
|
|
The exact error message is
CSPortDlg.obj : error LNK2019: unresolved external symbol _GetDevice referenced in function "public: void __thiscall CSPortDlg::OnBnClickedButton2(void)" (?OnBnClickedButton2@CSPortDlg@@QAEXXZ)
Cedric Moonen wrote: Your MFC application also needs to statically link to the MFC.
Can you please tell me how to modify the settings of my MFC application which access the DLL.
Many thanks.
Bhanu
|
|
|
|