Your understanding of is a in C++ (polymorphism, in general) is wrong.
A is B means A has at least the properties of B, possibly more, by definition.
This is compatible with your statements that a Dog has a Pet and that [the attributes of] a Pet is[are] a subset of [attributes] of Dog.
It's a matter of definition of polymorphism and inheritance. The diagrams you draw are aligned with the in-memory representation of instances of Pet and Dog, but are misleading in the way you interpret them.
Pet* p = new Dog;
The pointer p is defined to point to any Pet-compatible object, which in C++, is any subtype of Pet (Note: Pet is a subtype of itself by definition). The runtime is assured that, when the object behind p is accessed, it will contain whatever a Pet is expected to contain, and possibly more. The possibly more pat is what the Dog in your diagram is. The way you draw your diagram lends to a misleading interpretation.
Think of the layout of class-specific members in memory:
Pet: [pet data]
Dog: [pet data][dog data]
Cat: [pet data][cat data]
Now, whenever Pet *p points to, is required to have the [pet data] part, and optionally, anything else. From the above listing, Pet *p may point to any of the three. As long you use Pet *p to access the objects, you may only access the [pet data], because you don't know what, if anything, is afterwards. It's a contract that says This is at least a Pet, maybe more.
Whatever Dog *d points to, must have the [pet data] and [dog data]. So the only object in memory it may point to, above, is the dog. Conversely, through Dog *d, you may access both [pet data] and [dog data]. Similar for the Cat.
Let's interpret the declarations you are confused about:
Pet* p = new Dog; // [1] - allowed!
Dog* d = new Pet; // [2] - not allowed without explicit casting!
My understanding is that 1 should not be allowed without warnings because there is no way a pointer should be able to point to an object of its superset's type (Dog object is a superset of Pet) simply because Pet does not know anything about the new members that Dog might have declared (the Dog - Pet subset in the diagram above).
The pointer p expects to find [pet data] at the location it points to. Since the right-hand-side is a Dog, and every Dog object has [pet data] in front of its [dog data], pointing to an object of type Dog is perfectly okay.
The compiler doesn't know what else is behind the pointer, and this is why you cannot access [dog data] through p.
The declaration is allowed because the presence of [pet data] can be guaranteed by the compiler at compile-time. (this statement is obviously simplified from reality, to fit your problem description)
1 is equivalent of an int* trying to point to a double object!
There is no such subtype relationship between int and double, as is between Dog and Pet in C++. Try not to mix these into the discussion, because they are different: you cast between values of int and double ((int) double is explicit, (double) int is implicit), you cannot cast between pointers to them. Just forget this comparison.
As to [2]: the declaration states "d points to an object that has [pet data] and [dog data], possibly more." But you are allocating only [pet data], so the compiler tells you you cannot do this.
In fact, the compiler cannot guarantee whether this is okay and it refuses to compile. There are legitimate situations where the compiler refuses to compile, but you, the programmer, know better. That's what static_cast and dynamic_cast are for. The simplest example in our context is:
d = p; // won't compile
d = static_cast<Dog *>(p); // [3]
d = dynamic_cast<Dog *>(p); // [4]
[3] will succeed always and lead to possibly hard-to-track bugs if p is not really a Dog.
[4] will will return NULL if p is not really a Dog.
I warmly suggest trying these casts out to see what you get. You should get garbage for [dog data] from the static_cast and a NULL pointer for the dynamic_cast, assuming RTTI is enabled.
If you have base class derived object pointing by base class pointer, then you have the power of run time polymorphism in your hand, which gives you the ability to call the derived class implementation of the virtual member function. If we declare the member function as virtual in base class which needs to overridden in derived class, then you can decide at run time which implementation will be called at run time.
Association class is describing the relationship between classes. An abstract class is just 1 class, provides some abstraction behaviors that may be (but do not have to) derived, overridden from.
It is exactly what it says it is: a pointer to a base class. The assumption is that you have an object to a derived class, but actually hold a pointer to its base class. The following minimal example demonstrates this: class base{ public: virtual ~base(){} }; class derived: public base{}; int main() { base* p = new derived; // base class pointer to a derived instance. delete( p ); return(0); } Note that derived has an "is-a" relationship with base (derived is a base), thus the above code is perfectly legal. Moreover, because the base class destructor is declared virtual, when you delete p you automatically destroy the instance of derived before the instance of base, thus ensuring a clean teardown (without a virtual destructor, a dangling reference to derived would be left behind, which will only lead to problems further down the line). Taking things further, calling any virtual methods upon the base class automatically invokes the override in your derived class, thus ensuring that your derived class behaves accordingly, polymorphically, even though you only hold a pointer to the base class. In other words, the base class provides a generic interface that is common to all its derivatives, and you can call those generic methods via the base class pointer without ever needing to know the actual derived type. Remember that base classes should never know anything about their derivatives since a new derivative could be created at any time in the future and would therefore be impossible to predict in advance. But so long as the derivative makes use of the virtual functions (the generic interface) provided by the base class, there is never any need to know the actual type. The derivative's own v-table takes care of that for you, thus completely eliminating the need for expensive runtime type information and dynamic downcasts (which is always a sign of poor class design). This then makes it possible for your derived class overrides to call non-generic methods, thus extorting non-generic behaviour from what is essentially a generic, base class pointer.
The least-derived base classes are always constructed first, in the order specified by the derived class inheritance list. The most-derived class (the one you are actually instantiating) is always constructed last. Destruction is basically the reverse of construction. However, base class destructors must be declared virtual to ensure that the most-derived class destructor is called first, regardless of which class destructor is actually invoked. That is, if you hold a pointer to a base class that has no virtual destructor, deleting that pointer will only destroy the base class, not the derived class, leaving the derived class in an invalid state (because it no longer has an underlying base class) and with no way to recover the memory it consumes. It is important to remember that if you declare any virtual methods within a class, you must also declare the destructor virtual. A class without a virtual destructor is not intended to be derived from. If it has virtual methods, but no virtual destructor, it is not well-formed and must not be used as a base class.
There are two methods of casting one type to another: static casting and dynamic casting (both of which apply to pointers and references to objects). Statically casting a derived class to a base class is typesafe as the base class is guaranteed to exist if the derived class exists. However, static casting from a base class to a derived class is always considered dangerous as the conversion is not typesafe. Dynamic casting exists to cater for this scenario, however it is only possible when the base class is polymorphic (thus ensuring the required runtime information is available). If the conversion is not possible, the return value is NULL. However, it is considered bad programming practice to dynamically cast from a base class to a derived class. If the base class is polymorphic (which it must be), there is NEVER any need to dynamically cast between types. Virtual methods ensure correct behaviour. Whenever you are forced to dynamically cast from a base class to a derived class, consider redesigning the base class interface instead, as it is a clear sign of bad design. It is not dangerous, however; only static casting from a base class to a derived class is considered dangerous.
If you have base class derived object pointing by base class pointer, then you have the power of run time polymorphism in your hand, which gives you the ability to call the derived class implementation of the virtual member function. If we declare the member function as virtual in base class which needs to overridden in derived class, then you can decide at run time which implementation will be called at run time.
Association class is describing the relationship between classes. An abstract class is just 1 class, provides some abstraction behaviors that may be (but do not have to) derived, overridden from.
It is exactly what it says it is: a pointer to a base class. The assumption is that you have an object to a derived class, but actually hold a pointer to its base class. The following minimal example demonstrates this: class base{ public: virtual ~base(){} }; class derived: public base{}; int main() { base* p = new derived; // base class pointer to a derived instance. delete( p ); return(0); } Note that derived has an "is-a" relationship with base (derived is a base), thus the above code is perfectly legal. Moreover, because the base class destructor is declared virtual, when you delete p you automatically destroy the instance of derived before the instance of base, thus ensuring a clean teardown (without a virtual destructor, a dangling reference to derived would be left behind, which will only lead to problems further down the line). Taking things further, calling any virtual methods upon the base class automatically invokes the override in your derived class, thus ensuring that your derived class behaves accordingly, polymorphically, even though you only hold a pointer to the base class. In other words, the base class provides a generic interface that is common to all its derivatives, and you can call those generic methods via the base class pointer without ever needing to know the actual derived type. Remember that base classes should never know anything about their derivatives since a new derivative could be created at any time in the future and would therefore be impossible to predict in advance. But so long as the derivative makes use of the virtual functions (the generic interface) provided by the base class, there is never any need to know the actual type. The derivative's own v-table takes care of that for you, thus completely eliminating the need for expensive runtime type information and dynamic downcasts (which is always a sign of poor class design). This then makes it possible for your derived class overrides to call non-generic methods, thus extorting non-generic behaviour from what is essentially a generic, base class pointer.
A pointer in itself is not an object, because it is not an instance of a class. Of course you can define a class which has only one member, which is a pointer. class Pointer { public void *ptr; }; Pointer p, q, r;
The least-derived base classes are always constructed first, in the order specified by the derived class inheritance list. The most-derived class (the one you are actually instantiating) is always constructed last. Destruction is basically the reverse of construction. However, base class destructors must be declared virtual to ensure that the most-derived class destructor is called first, regardless of which class destructor is actually invoked. That is, if you hold a pointer to a base class that has no virtual destructor, deleting that pointer will only destroy the base class, not the derived class, leaving the derived class in an invalid state (because it no longer has an underlying base class) and with no way to recover the memory it consumes. It is important to remember that if you declare any virtual methods within a class, you must also declare the destructor virtual. A class without a virtual destructor is not intended to be derived from. If it has virtual methods, but no virtual destructor, it is not well-formed and must not be used as a base class.
There are two methods of casting one type to another: static casting and dynamic casting (both of which apply to pointers and references to objects). Statically casting a derived class to a base class is typesafe as the base class is guaranteed to exist if the derived class exists. However, static casting from a base class to a derived class is always considered dangerous as the conversion is not typesafe. Dynamic casting exists to cater for this scenario, however it is only possible when the base class is polymorphic (thus ensuring the required runtime information is available). If the conversion is not possible, the return value is NULL. However, it is considered bad programming practice to dynamically cast from a base class to a derived class. If the base class is polymorphic (which it must be), there is NEVER any need to dynamically cast between types. Virtual methods ensure correct behaviour. Whenever you are forced to dynamically cast from a base class to a derived class, consider redesigning the base class interface instead, as it is a clear sign of bad design. It is not dangerous, however; only static casting from a base class to a derived class is considered dangerous.
By default, all of the members of a class are private and, by default, all of the members of a structure are public.Structure are value type where as class are reference type.'this' pointer will work only in class.Inheritance between classes is also private by default, and inheritance between structs is public by default.Classes support polymorphism, whereas structure do not.
Multiple Inheritance : we can inherit more than one class in the same class. Multi-Level Inheritance: where one class can inherit only one base class and the derived class can become base class of some other class.
We can access a Friend function from any other class in which friend function is introduced or declared even if the other class is not a member of first class. But when we use normal member function, we can have its access only in the derived classes of the first class. This is the basic difference between a friend function and a normal member function.
The difference between the Class 365 and Class 465, 466 is basically the cost.
difference between inclusive and exclusive class interval
What is the difference between buying a 1st class and a 2nd class ticket on the train in England?