Saravanan
Saravanan

Reputation: 7854

question on basic oops concepts

I just want to find an answer to this question

Let A be a parent class with B,C the child classes.

Now we create objects as follows,

  1. A o1 = new A();
  2. B o2 = new B();
  3. C o3 = new C();

  4. A o4 = new B();

  5. B o5 = new A();
  6. C o6 = new B();

From these which will all create errors and why.. I got confused a lot because from 6 we know that it is an error because b may have some specialized variables and 7 is possible and 8 is not possible.

If i'm wrong please correct me and also,

  1. A o7 = o4;
  2. B 08 = o5;

Kindly suggest me the right answers and with explanations and also give me links for tutorials with this kind of puzzles.

Upvotes: 1

Views: 1072

Answers (4)

Saurabh Gokhale
Saurabh Gokhale

Reputation: 46395

In your question, as you mentioned,

A is the superclass,
B,C are two different subclasses of A. i.e B extends A, C extends A

Let's go step by step

Now, your assginment of references to different objects is right upto 4th step.
i.e

A o1 = new A();   //Creates a new A() object and assigns it to ref. of type A. So  Correct.
B o2 = new B();   //Creates a new B() object and assigns it to ref. of type B. So  Correct.
C o3 = new C();   //Creates a new C() object and assigns it to ref. of type C. So  Correct. 

A o4 = new B();   //Subclass object being assigned to a superclass reference. That's also correct.  

Now at the 5th step,

B o5 = new A();   //Will not compile since a superclass object is assigned to a subclass reference.  
                  //This is not allowed in Java.    

Reason : It is because the superclass has no idea what features did its subclass add to itself, while inheriting. So this assignment of superclass object to subclass reference is incorrect and futile.


Now at the 6th step,

C o6 = new B();  // There isn't any hiearchical relationship between B and C. 
                 // They are just subclass of class A. This won't compile.  

Now at the 7th step,

A o7 = o4;      //Correct. Because both the references i.e o4 & o7 are of same type (A).
                // Hence, will compile.  

Now at the 8th step,

B 08 = o5;     // It is wrong because the 5th step was itself wrong.  
               // So it will produce a compile time error.

Upvotes: 1

Mahesh
Mahesh

Reputation: 34625

Assuming all objects are of pointer types-

1. A *o1 = new A();   // Correct
2. B *o2 = new B();   // Correct
3. C *o3 = new C();   // Correct

4. A *o4 = new B(); // A pointer to a derived class is type-compatible with a pointer to its base class. This is up casting which acts by default.
5. B *o5 = new A(); // Wrong because the other-wise relationship of the above comment isn't true. Though there is a separate concept called Down-casting which isn't valid here.
6. C *o6 = new B();  // Wrong : C, B has no hierarchial relationships

7. A *o7 = o4;      // Correct because o4, o7 are both of same type
8. B *o8 = o5;      // Wrong. Since, 5 itself is wrong.

Explanation for 4 & 5:

  1. new B() calls A's constructor followed by B's constructor. So, we have sub-objects of type A*,B*. Since, there is a sub-object of type A*, the lvalue can point to it which is also equal to of type A*. This is helpful to access base class overridden virtual methods in derived class.

  2. new A() constructs an object of type A* and returns it's address. So, return type is of A* but the receiving type is of B*. So, they both are incompatible and is wrong.

Example: Output results

#include <iostream>
using namespace std;
class A
{
    public:
    A(){
        cout << " \n Constructor A \n";
    }
    virtual ~A(){
        cout << "\n Destructor A \n";
    }
};

class B: public A
{
    public:
    B(){
        cout << " \n Constructor B \n";
    }
    ~B(){
        cout << "\n Destructor B \n";
    }

};

class C: public A
{
    public:
    C(){
        cout << " \n Constructor C \n";
    }
    ~C(){
        cout << "\n Destructor C \n";
    }

};

int main()
{
    A* obj1 = new A;
    std::cout<< "******************************" << std::endl;

    A* obj2 = new B;
    std::cout<< "******************************" << std::endl;

    A* obj3 = new C;
    std::cout<< "******************************" << std::endl;

    delete obj1;
    std::cout<< "******************************" << std::endl;

    delete obj2;
    std::cout<< "******************************" << std::endl;

    delete obj3;
    std::cout<< "******************************" << std::endl;

    return 0;
}

Results:

Constructor A


Constructor A

Constructor B


Constructor A

Constructor C


Destructor A


Destructor B

Destructor A


Destructor C

Destructor A


Notice that the order of destruction is reverse to the order of construction.

Upvotes: 3

ocodo
ocodo

Reputation: 30248

This isn't a direct answer to your question, because I think the other guys have answered your case. However, I noticed that you seem to be under the illusion that objects get type checked against memory allocation.

They don't they are checked against class definitions. Let me give you an example which I hope will bring a sense of understanding:

Say we have two classes that have been defined in the same namespace, they have identical methods and properties. The only difference is their classname. As far as the compiler and runtime are concerned, these two classes would bear no relationship whatsoever.

You would have to define another OOP way of relating them. For example, you can have both classes inherit the same parent, or have them both implement the same interface.

Using the Interface method is often preferable, since many classes which bear little relationship can implement an Interface so that other objects can interact with them via the Interface methods.

OOP is quite tricky to understand, because it's really about abstraction, and bears very little relationship to coding the metal. Once you understand what the abstractions are for and how they are used together, things get easier. Good luck.

Upvotes: 1

Andrew Marshall
Andrew Marshall

Reputation: 96934

All will work except #5 & #6, in your second set, #2 will not work simply because #5 doesn't (also because 08 is not a valid variable name).

#5 doesn't work because B may have methods that are not a part of A, so new A() doesn't return an object compatible with B.

In general, you can do:

ChildOne c1 = new ChildOne();
Parent p1 = new ChildOne();

whereas you cannot do:

ChildOne c1 = new ChildTwo();
ChildOne p1 = new Parent();

Upvotes: 1

Related Questions