class A
{
public:
//EDIT: No more memory leaks now :P
virtual ~A()
{
}
};
class B : class A
{
};
int main()
{
A* obj = new B;
return 0;
}
🔒 Locked
A* obj = new B (basic OOP question)
Advertisement
Original Post
Given this: What exactly "is" obj? You can only access members declared in A but not B but if B redefines a function in A (assuming the function in A is virtual) then the B function is called. Is it "a A object that polymoprhically calls B functions"? [Edited by - load_bitmap_file on November 17, 2004 5:38:32 PM]
Quote:
Is it "a A object that polymoprhically calls B functions"?
No. Its a B object (it uses sizeof(B) memory), but you are "pretending" its an instance of A when you access it.
Imagine a stencil A with only half the alphabet. And a stencil B with the whole alphabet. You use B to write out the whole alphabet, but then place stencil A over the output. The underlaying representation is B, but you can only get to the bits they have in common.
My analogy breaks down at virtual functions. All they do really is "magically" replace functions with the version furthest down the inheritance tree.
After writing this Im not exactly certain what the question was :-) I'll post anyway as I think you were asking "how does inheritance/polymorphism work".
Alan
obj is a pointer to an object of, or derived from, type A.
obj in this case points to an object of type B, which is derived from type A.
You have a memory leak.
obj in this case points to an object of type B, which is derived from type A.
You have a memory leak.
obj is a pointer that points to a B object. However, the compiler can't be sure of that at compile-time, (the pointer itself is of the type A*, so all the compiler knows is that obj either points to an A object or one of its subclasses). Because of that, the compiler won't let you use any B members on an A pointer without an explicit cast. If your base class has at least one virtual function, you can use runtime checking to see if the object pointed to is, in fact, a certain subclass. For example:
Output:
MyBaseClass
ClassB
Unable to cast to ClassA
Successful cast to: ClassB
Dynamic casts will only work if your base class has at least one virtual function. As far as what implementation of a function gets called, if the function isn't virtual, the compiler will use the type of the pointer to determine which implementation to call; if the function is virtual, the compiler will use the virtual function tables to correctly identify which implementation should be called at runtime.
#include <iostream>using namespace std;class MyBaseClass { public: virtual char* MyFunc(); char* OtherFunc();};char* MyBaseClass::MyFunc() { return "MyBaseClass"; }char* MyBaseClass::OtherFunc() { return "MyBaseClass"; }class ClassA : MyBaseClass { public: virtual char* MyFunc(); char* OtherFunc();};char* ClassA::MyFunc() { return "ClassA"; }char* ClassA::OtherFunc() { return "ClassA"; }class ClassB : MyBaseClass { public: virtual char* MyFunc(); char* OtherFunc();};char* ClassB::MyFunc() { return "ClassB"; }char* ClassB::OtherFunc() { return "ClassB"; }int main(int argc, char** argv) { MyBaseClass* ptr = (MyBaseClass*) new ClassB; //All the compiler knows is that ptr points to a MyBaseClass object cout << ptr->OtherFunc() << endl; //OtherFunc isn't virtual, so the compiler calls MyBaseClass's implementation cout << ptr->MyFunc() << endl; //MyFunc is virtual, so the compiler is able to determine which implementation to call at runtime ClassA* ptrA = dynamic_cast<ClassA*>(ptr); if(ptrA != NULL) cout << "Successful cast to: " << ptrA->OtherFunc() << endl; else cout << "Unable to cast to ClassA" << endl; //We try to cast ptr to a pointer to ClassA, but since the object pointed to is a ClassB, ptrA is now NULL ClassB* ptrB = dynamic_cast<ClassB*>(ptr); if(ptrB != NULL) cout << "Successful cast to: " << ptrB->OtherFunc() << endl; else cout << "Unable to cast to ClassB" << endl; //We try to cast ptr to a pointer to ClassB, and it works since the object pointed to is a ClassB, ptrB now points to the ClassB object //Since the compiler knows that ptrB is pointing to a ClassB object, it can use ClassB's implementation of OtherFunc delete ptr; //Delete the object pointed to //Note: it is highly recomended that base classes have virtual destructors, so that subclasses can clean up any memory that only they would allocate }Output:
MyBaseClass
ClassB
Unable to cast to ClassA
Successful cast to: ClassB
Dynamic casts will only work if your base class has at least one virtual function. As far as what implementation of a function gets called, if the function isn't virtual, the compiler will use the type of the pointer to determine which implementation to call; if the function is virtual, the compiler will use the virtual function tables to correctly identify which implementation should be called at runtime.
Wow, it took me a long time to write that. When I started nobody else had replied! [lol]
Quote:
Original post by TheBluMage
Wow, it took me a long time to write that. When I started nobody else had replied! [lol]
Rabbit punches
[Edited by - petewood on November 17, 2004 4:54:02 PM]
Thanks for the replies.
So.. would you call obj a A pointer to a B object?
So.. would you call obj a A pointer to a B object?
The NATURE of obj is that it is a pointer, which points to one of the following:
1) An object of type A
2) An object that inherits from type A
3) NULL / 0 / Nothing.
4) Where an object of type A or inheriting from type A used to be (a "dangling pointer", dangerous to use because the object no longer exists)
5) Something else entirely (even more dangerous to use, results completely undefined if using it appropriately)
The VALUE of obj in your example is that it is a pointer to an object of type B.
1) An object of type A
2) An object that inherits from type A
3) NULL / 0 / Nothing.
4) Where an object of type A or inheriting from type A used to be (a "dangling pointer", dangerous to use because the object no longer exists)
5) Something else entirely (even more dangerous to use, results completely undefined if using it appropriately)
The VALUE of obj in your example is that it is a pointer to an object of type B.
Quote:
Original post by Zahlman Quote:
Original post by Fruny
And to add to what petewood said, A's destructor should be virtual, or you'll be in a heap of trouble.
Unless he creates a B with automatic storage; then he's in a stack of trouble. [grin]
Funny, but wrong - yes I'm a pedant [grin]
If it's an automatic variable then the type will be correct when its destructor is called as the compiler has all the type information available. Along similar lines virtual functions can be inlined on automatic local variables.
You don't technically need a virtual destructor on a base class if you will never be deleting objects through the base class' pointer. The reason to make a base class destructor virtual is because it's the easiest way to avoid forgetting to put virtual destructors in derived classes when they are eventually really needed.
Quote:
Original post by Zahlman Quote:
Original post by Fruny
And to add to what petewood said, A's destructor should be virtual, or you'll be in a heap of trouble.
Unless he creates a B with automatic storage; then he's in a stack of trouble. [grin]
Crazy word games :0
Thanks again to everyone.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement