|
in that case, you need to :
1. create a font object that reflects the font you're going to use when you draw the text
2. create a DC
3. select your font into that DC
4. use something like DrawTextEx or CDC::GetTextExtent to measure the text
Cleek | Image Toolkits | Thumbnail maker
|
|
|
|
|
class Derived: public string <br />
{<br />
public:<br />
~ Derived() { --destr;}<br />
};<br />
int main()<br />
{<br />
string * p = new Derived;<br />
delete p;
cout>> destr >>endl;
}
Class Derived publicly inherits from Class String
My question is, is
String *p = new Derived;
same as
String *p;<br />
p = new Derived;
-- modified at 17:38 Tuesday 4th July, 2006
|
|
|
|
|
Deriving from std::string is asking for trouble...
--
Based on a True Story
|
|
|
|
|
what are virual destructors? I'm tryin to understand this file
why do we have a destructor function from a derived class which is empty
class ObjectRoot <br />
{<br />
public:<br />
<br />
virtual ~ObjectRoot<br />
<br />
};<br />
<br />
<br />
<br />
class Ball : public ObjectRoot <br />
{<br />
public :<br />
<br />
virtual ~Ball<br />
};<br />
<br />
ObjectRoot::~ObjectRoot<br />
{<br />
......<br />
......<br />
......<br />
}<br />
<br />
<br />
Ball::~Ball <br />
{<br />
}
CAN ANYONE TELL ME WHAT IS GOING ON HERE PLZ
-- modified at 16:59 Tuesday 4th July, 2006
|
|
|
|
|
The virtual destructor allows the destructor of derived classes to be called when deleting the instance through the base class.
In other words, an instance of Ball can be assigned to an ObjectRoot pointer:
ObjectRoot* pBase = (ObjectRoot*) new Ball;
and then deleted:
delete pBase;
The virtual destructor ensures that Ball's destructor will be called.
Often, destructors do nothing, but the empty virtual implementation is left just in case something later is added.
Anyone who thinks he has a better idea of what's good for people than people do is a swine.
- P.J. O'Rourke
|
|
|
|
|
class A {
public:
A() { }
~A() { }
};
class B : public A {
public:
B() { }
~B() { }
};
B* b = new B();
delete b;
A* a = new B();
delete a;
When a C++ compiler sees a method call, it first checks to see if the method is virtual or not. If it is not virtual, it will use the object variable's static type information, to determine what method to call. If the variable is of type B* , it will first look in B 's definition, and fallback on A if no matching method could be found.
If the method is virtual, the compiler will generate code which calls the method furthest down in the inheritance tree.
The same idea applies to destructors. If you call delete on b , as above, the compiler will first check if the destructor is virtual in the class hierarchy. In this case, it's not. Therefore it will inspect B 's definition, as the variable is of type B* . It'll find the destructor, and call it. After that, the compiler will generate code which calls all parent classes' destructors. In the case of the variable a , the compiler will, as earlier, see that the destructor is not virtual, and will therefore look into A 's definition for the destructor (a is of type A* ). The compiler will then generate code which calls A::~A() , and nothing more. You can easily understand that this is a problem, if B::B() did stuff like new ... .
Two analogies: virtual destructors are like doubly linked lists; you can always find the end of the list from any node in the list - meaning that the compiler will always call the destructor furthest down the inheritance tree, and then work its way back to the root. Non-virtual destructors are like singly linked lists; you can not find the end of the list from all nodes in the list - meaning that the compiler can't call the destructors which comes "after" the class in question.
The golden rule: virtual methods are virtual, if and only if, the first declaration is declared as virtual.
--
Transmitido en Martian en SAP
|
|
|
|
|
Hey, thanks for the descriptive information on destructors. The only problem is that Im a beginner.
A* a = new B();
how can a Pointer to an A object create a new B object?
its like saying
int *a = new double;
Im definately not right but, I have a hard time thinking how it looks like
Please help me out here.
Thanks,
Jay
|
|
|
|
|
Jay03 wrote: A* a = new B();
how can a Pointer to an A object create a new B object?
its like saying
int *a = new double;
No, not really. A double doesn't inherit from int. With your A and B, the story is different.
When you declareclass B : public A you state a relationship between class A and B. That relationship is "B is an A". This relationship means that wherever you can put an A*, you can put a B*. For instance, suppose you have the function
void function(A* a) { ... } it means that you can do this:
B* b = ...;
function(b); . Why? Because we've stated that B is an A. This is the essence of inheritance. You use these relationships to make your programs more modular and interchangeable.
For example: Suppose you have the class Instrument . It has the virtual method PlayNote(char* note) . Suppose note is a string with a "C", "A", "B#", or any other playable note. The class Guitarr , Flute and Organ all derive from Instrument . Their versions of PlayNote produces the corresponding sound. With this inheritance setup, you can do things like this:
Instrument* instrument = new Guitarr();
instrument->PlayNote("C");
instrument->PlayNote("F");
instrument->PlayNote("G"); This will make each call to PlayNote produce guitarr sounds. Should you ever want to switch to an organ, just do this instead:
Instrument* instrument = new Organ();
instrument->PlayNote("C");
instrument->PlayNote("F");
instrument->PlayNote("G"); One word switched, and the program now behaves very differently (and hopefully sounds a lot more different too!)
Now, using inheritance, you can make your own orchestra. How? Well, check this out:
Instrument* orchestra[3];
orchestra[0] = new Guitarr();
orchestra[1] = new Flute();
orchestra[2] = new Organ();
for(int i = 0; i < 3; ++i) {
instrument->PlayNote("C");
instrument->PlayNote("F");
instrument->PlayNote("G");
} See how easy that was? All we had to do was to declare an array to hold 3 pointers to Instrument . Then we stuffed each entry with an various instruments. The reason we can do this, is that because of the relationship "Guitarr is an Instrument", "Flute is an Instrument", and "Organ is an Instrument".
This is just one tiny portion of what you can do with inheritance. The tricky part is how you express it in the C++ language. You have already faced one learning obstacle in the language: virtual and non-virtual methods and destructors. For this example to work, PlayNote must be a virtual method. Why? Well, had the method not been virtual, and you have calls like this:
Instrument* instrument = new Flute();
instrument->PlayNote("C"); the compiler would have generated a call to the version of PlayNote that is declared in Instrument . For all non-virtual methods (and destructors), the compiler looks at the type of the variable to determine which method to call. In this case, the type of the variable is Instrument* . From that the compiler deduces that the method to be called is Instrument::PlayNote . If you make the method virtual , the compiler won't be so "dumb" about it, and call the correct method (in this case Flute::PlayNote ). Why on earth is the compiler behaving this dumb by default you might ask? The reason is purely technical, although very valid in some scenarios, and certainly was valid back in the days when C++ was designed. When you declare a virtual method, the compiler adds extra data to the object (typically 4 bytes per object in a 32 bit environment), which it uses to determine which method to call. This overhead is unbearable in some scenarios, as internal memory may be a scarce resource.
Note that this "is a"-relationship only holds in one direction. Suppose we have class B : A again. Given this, we cannot write code like
B* b = new A(); . Why? Because the relationship does not say "A is a B". To elaborate on why this is correct, see here:
class A {
public:
virtual void Method() { cout << "A::Method called"; }
};
class B : public A {
public:
virtual void Method2() { cout << "B::Method2 called"; }
};
B* b = new A();
b->Method();
b->Method2(); Generally speaking, whatever you declare in A is also declared in B automatically. That is to say that not only can you call Method2 through B, you can also call Method . The same does not hold for A - whatever's declared in B is not declared in A. With this in mind, what method will be called here: b->Method2() ? The variable b is of type B* . From this, the compiler deduces that there is indeed a method named Method2() available. But.. keep in mind that we didn't create an object of class B , we created one of class A . A doesn't have the method Method2 . Should you try, the C++ compiler catch the error, emit an error message and stop the compilation. (So there's no need to worry about it! )
Without a whiteboard and a lab, my pedagogical skills stretches only this far (although, I hope I made some sense). I advise you to pick up the book C++ Primer (4th Edition)[^] at the bookstore or your local library (any edition will do, as the basics of C++ hasn't changed much over the years). It'll give you a far better foundation that any of us could give you on a web forum. Also, make sure you experiment a lot. If in doubt; write it and test it - that methodology and armed with a good book is the best way to learn in my opinion.
By the way, in C++, it's good manner to put the asterisk adjacent to the type, rather than the variable. Like this: Type* pointer . I could go on as to why that's the norm, but I feel I would be giving you information that you don't need right now. Only old timers (former C programmers) and stubborn people put the asterisk adjacent to the variable name.
--
[LIVE] From Omicron Persei 8
|
|
|
|
|
class Instrucment {
public:
virtual void PlayNote(char* note)
};
Instrument* instrument = new Guitarr();
instrument->PlayNote("C");
instrument->PlayNote("F");
instrument->PlayNote("G");
What if PlateNote(char* note) was not virtual
how would u call it
instrument->Instrument::PlayNote("C") ; //????
-- modified at 20:26 Tuesday 4th July, 2006
|
|
|
|
|
Then you'd have to do something like this:
Guitarr* g = new Guitarr();
Flute* f = new Flute();
Organ* o = new Organ();
f-> PlayNote("C");
f-> PlayNote("F");
f-> PlayNote("G");
g-> PlayNote("C");
g-> PlayNote("F");
g-> PlayNote("G");
o-> PlayNote("C");
o-> PlayNote("F");
o-> PlayNote("G"); Not very flexible, as you can see.
--
Filmed on LocationLast modified: den 4 juli 2006 19:39:38 --
|
|
|
|
|
Thanks for your help!!
I really appreciate it
I UNDERSTAND DESTRUCTORS NOW!!!
Cheers,
Jay
|
|
|
|
|
I'm glad to be of service! Remember this simple rule; if it's not virtual - it's the type of the variable that determines which method will be called!
--
Mr. Bender's Wardrobe by ROBOTANY 500
|
|
|
|
|
Any info on how to add some scripting abibilies to an existing MFC application ?
for example, is it possible to use VB ( or other script language, like python, ... ) to call functions in our application ?
We would like to let some users augment some functionalities, automate some processes by letting them write some simple scripts.
Any resources ? links ?
Thanks.
Maximilien Lincourt
Your Head A Splode - Strong Bad
|
|
|
|
|
Maximilien wrote: is it possible to use VB ( or other script language, like python, ... ) to call functions in our application ?
it's possible to integrate a scripting language into C++ so that you can expose specific parts of your application to the scripting language. and most scripting languages are designed to be used this way.
Maximilien wrote: Any resources ? links ?
Google has a lot of links. ex: Python[^] Lua[^] Perl[^]
Cleek | Image Toolkits | Thumbnail maker
|
|
|
|
|
Hey, I've created a static library (in VC6) and want it all under a namespace. The library builds successfully, but when I link an app. with it, I get link errors like:
error LNK2001: unresolved external symbol "class LibNamespace::CGraphicsSystem LibNamespace::globalGSys" (?globalGSys@LibNamespace@@3VCGraphicsSystem@1@A)
How does one do namespaces in a library with .h and .cpp files??
in my graphicsSystem.hpp I have
namespace LibNamespace{
...
}
and in the implementation file I have
using namespace LibNamespace;
globalGSys is declared in graphicsSystem.hpp under the LibNamespace namespace:
extern CGraphicsSystem globalGSys;
I've also tried:
extern LibNamespace::CGraphicsSystem globalGSys;
Still linker errors. Please help me.
Joel Becker
|
|
|
|
|
I couldn't see anything wrong with namespace stuff. Have you exported your class?
Best,
Jun
|
|
|
|
|
Hey, Jun, thanks for your reply. I didn't see it until after I submitted my reply to myself (I don't USUALLY talk to myself).
Everythings working now with linking with the app.
Later,
Joel
|
|
|
|
|
I didn't actually help, but you're welcome
Best,
Jun
|
|
|
|
|
Myself,
Nevermind. I figured it out finally. It was a problem of namespace-wide variables:
In the header file i had:
namespace LibNamespace{
...
extern CGraphicsSystem GSys;
...
}
In the implementation:
CGraphicsSystem GSys;
I NEEDED TO WRAP THE IMPLEMENTATION'S DEFINITION IN THE NAMESPACE:
namespace LibNamespace{
...
extern CGraphicsSystem GSys;
...
}
using LibNamespace;
CGraphicsSystem::CGraphicsSystem()
{...}
...
(Is this educational to anyone else, or am I just namespace-naive?)
Myself
|
|
|
|
|
I am working on a project which has .hh file extension
#include <RTI.hh>
What is the difference between .h files and .hh files
I also noticed how it is not from the same directory as the project files rather from the standard library because it is #include <....> rather than #include "...."
Does anyone know what is going on?
If anyone has worked with such files please help me out here.
Thanks,
Jay
-- modified at 13:16 Tuesday 4th July, 2006
|
|
|
|
|
basically, .h and .hh are the same things : C/C++ header files.
the fact that the file is included with <> indicated to the compiler to search the file in its (the compiler's) includes folder instead of looking in the project directory (this is the purpose of including with "" ).
TOXCCT >>> GEII power
[VisualCalc 3.0 updated ][Flags Beginner's Guide new! ]
|
|
|
|
|
Thats exactly what I thought but why do we have two different extensions in the Standard library
#include <abc.h> and #include <def.hh> Is there any specific reason why we name it that way??????
Thanks,
Aravinth
-- modified at 13:43 Tuesday 4th July, 2006
|
|
|
|
|
i don't really know... maybe to explicitely differ between C and C++ headers... it's quite similar to .hpp files.
TOXCCT >>> GEII power
[VisualCalc 3.0 updated ][Flags Beginner's Guide new! ]
|
|
|
|
|
Im pretty sure Zac Howland knows. He works with RTI (Run time Infrastructure)
thanks for your help TOXCCT
Cheers,
Jay
|
|
|
|
|
Jay03 wrote: Im pretty sure Zac Howland knows
maybe,but this is not specific to RTI AFAIK...
Jay03 wrote: thanks for your help TOXCCT
welcome.
TOXCCT >>> GEII power
[VisualCalc 3.0 updated ][Flags Beginner's Guide new! ]
|
|
|
|
|