|
|
Thanks, and one more question, does GetDriveType return DRIVE_CDROM for dvd's as well? Because there wasn't any mention of DVDs in the MSDN article.
There is sufficient light for those who desire to see, and there is sufficient darkness for those of a contrary disposition.
Blaise Pascal
|
|
|
|
|
sashoalm wrote: does GetDriveType return DRIVE_CDROM for dvd's as well?
Yes, it will return DRIVE_CDROM for all drives which support reading a CD-ROM. One way to determine if the device is actually a DVD-drive is to use DeviceIOControl such as follows:
#include <winioctl.h>
BOOL DeviceSupportsDVDMedia(TCHAR *szDrive)
{
BOOL bRet = FALSE;
if(NULL != szDrive && DRIVE_CDROM == GetDriveType(szDrive))
{
GET_MEDIA_TYPES media[CHAR_MAX];
TCHAR szVol[MAX_PATH] = {0};
DWORD dwBytesRet =0;
int iSize = CHAR_MAX * sizeof(GET_MEDIA_TYPES);
_stprintf(szVol,_T("\\\\.\\%c:"),szDrive[0]);
HANDLE hDevice = CreateFile(szVol,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,0);
if(INVALID_HANDLE_VALUE != hDevice)
{
if(DeviceIoControl(hDevice,IOCTL_STORAGE_GET_MEDIA_TYPES_EX,NULL,0,media,iSize,&dwBytesRet,FALSE))
{
bRet = FILE_DEVICE_DVD == media->DeviceType;
}
}
}
return bRet;
}
Best Wishes,
-David Delaune
[Updated January, 15, 2010]
I was contacted by a member regarding this code sample. I noticed the code sample was very poorly written (sorry bout that). I have updated it.
modified on Saturday, January 15, 2011 4:33 AM
|
|
|
|
|
DriveComboBox[^].
Of one Essence is the human race
thus has Creation put the base
One Limb impacted is sufficient
For all Others to feel the Mace
(Saadi )
|
|
|
|
|
?
modified on Tuesday, January 20, 2009 4:02 AM
|
|
|
|
|
You can't instantiate an abstract class. Full stop. No argument. All you can do is derive a class from the abstract class that implements the abstract method(s) and instantiate one of those. The derived class pointer is convertible to a pointer to the abstract base class, so can be used in its place - see the code below.
class A{
public :
A(){};
virtual ~A(){};
virtual void do()=0;
};
class B : public A
{
public:
B() {}
virtual ~B() {}
virtual void do() { std::cout << "In B::do\n"; }
}
void Blah(A* pA) { pA->do(); }
void main()
{
B* pB=new B();
Blah(pB);
}
I've also made the destructor virtual - it's always safest to make destructors virtual if a class has any virtual method, in case the destructor gets called from a base class pointer/reference.
|
|
|
|
|
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.
|
|
|
|