Why C++ cannot initialize a variable of type "derived class" with an rvalue of type "super class"?

Please consider the code below:

class a { int a1; public: a() { printf("foo1\n"); } }; class b : public a { int a2; public: b() { printf("foo2\n"); } }; int main (int argc, const char * argv[]) { b *instance = new a(); return 0; }

It gives Error: Cannot initialize a variable of type "b*" with an rvalue of type "a*" Works fine when I write

a *instance = new b();

The output is:

foo1 foo2

Can someone please explain me the reason? I would be extremely grateful :)

Another thing, if I write

instance->~a();

above return 0; nothing extra happens. Is this because a constructor can be called only once?

-------------Problems Reply------------

Let's make this a little more concrete:

class Animal
{
int a1;

public:
Animal()
{
printf("Animal\n");
}
};

class Bat : public Animal
{
int a2;
public:
Bat()
{
printf("bat\n");
}
};
int main (int argc, const char * argv[])
{
Bat *instance = new Animal();
return 0;
}

Can you see now why this might not be valid? What you create with new Animal() can be any type of Animal. It may not be valid to assign it to a variable that is a Bat because it may not be a bat.

b is an a.
a isn't a b.


You can put a instance of type Giraffe in a variable of type Animal.
However, you cannot put an instance of the Animal in a variable of type Giraffe (What if it's a Porcupine?)

A derived class is, by definition, something that can do a superset of what a base class can do. The derived class can do everything the base class can, but not vice-versa. Therefore, it makes sense to treat a derived class as if it were the base class but not vice-versa. For example:

class Animal {
void eat();
};

class Dog : public Animal {
void bark();
}

It makes perfect sense to treat a Dog as a generic Animal, but there would be no reasonable thing for a generic Animal to do if ordered to bark.

Since a is not a b, you can't assign a pointer to b to an object of type a.

Since b is an a, it is indeed working fine the other way around.

b is a type of a. However, a is not a type of b. If b contained additional members, then what happens when you try and access them if b really refers to an object of type a.

It's not a safe cast.

Remember this always, You cannot assign a base class object to a derived class pointer. [Derived class object] is a [Base class object]. The reverse is not true.

The problem is with "is a" relationship. Object of class a is not an object of class b so

b *instance = new a(); // won't work

would mean that you try to set a pointer to class b onto something that is not an object class b. At the same time you could do the opposite:

a* instance = new b(); //will work

since objects of class b are also objects of class a and so here you would set a pointer to class a onto something that is indeed an object of class a.

Regarding the destructor -

If the static type of the operand is different from the dynamic type, then it's static type behaves as a base class and it's destructor must be virtual.

Also, pointer/reference of a derived class is type compatible with pointer/reference of base class. But the otherwise is not true. ( No transitive nature )

In your case -

a *instance = new b(); // This should be correct way.

The static type of instance is a* while the dynamic type is b*. So, a acts as a base class and it's destructor must be virtual.

You can't substitute an a for a b because a doesn't have all of b's functionality. Thus it makes no sense to make such an assignment.

For your second part, 99% of the time you say delete var to destroy something allocated with new instead of calling the destructor explicitly, which is an advanced topic.

Category:c# Views:0 Time:2011-07-15
Tags: oop

Related post

  • cannot initialize a parameter of type UIRemote NotificationType with an rvalue of type int 2011-12-14

    When I use [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; to register remote push notificatioin, an error occurs saying cannot in

  • How to test if Type derives from an abstract base generic type? 2012-09-26

    Hey I have an abstract generic type BList<TElement> where TElement : Career. Career is abstract type too. Given a type T, how do I test if it is a BList type? And how can I cast to the base class? I tried (BList<Career>)object but the com

  • How to default-initialize local variables of built-in types in C++? 2010-04-06

    How do I default-initialize a local variable of primitive type in C++? For example if a have a typedef: typedef unsigned char boolean;//that's Microsoft RPC runtime typedef I'd like to change the following line: boolean variable = 0; //initialize to

  • How to initialize several variables in a for (;;) loop in C? 2010-07-27

    I thought one could initialize several variables in a for loop: for (int i = 0, char* ptr = bam; i < 10; i++) { ... } But I just found out that this is not possible, gcc gives the following error: error: expected unqualified-id before 'char' Is it

  • what can you initialize global variables to in c++ 2011-05-01

    Can you intialize global variables in c++, and if possible, what values are allowed? --------------Solutions------------- Yes, of course you can initialize globals. For built-in types, you can use any value you could use for assignment (and you can a

  • Initialize two variables on same line 2011-05-14

    I'm having trouble finding an authoritative example or discussion of this concept. If I have 2 variables in my Ruby method that are numbers, and I need to initialize them to zero. They will be used as counters. Is this OK or safe? It works in my test

  • C# - Initialize a variable without knowing what its going to be 2011-06-28

    I have two different tables in my database, and each are displayed to the user based on their "SortOrder". I have written two functions that take a row (or entity) and swaps its sort order with the one nearest it (up or down, depending on which funct

  • Why can't I initialize a variable-sized array? 2011-07-09

    GCC gives no error when you initialize a variable-sized array as long as the variable is const, but when it isn't, it won't compile. What's the reason behind this? What's so wrong with doing: int size = 7; int test[size] = {3, 4, 5}; That won't compi

  • C structure initialization with variable 2011-10-09

    I've run into a problem that seems to not be addressed by any of the C Standards after C89 save for the mention that structures initialization limits had been lifted. However, I've run into an error using the Open Watcom IDE (for debugging) where the

  • Why we must initialize a variable before using it? 2011-10-16

    Possible Duplicate: What happens to a declared, uninitialized variable in C? Does it have a value? Now I'm reading Teach Yourself C in 21 Days. In chapter 3, there is a note like this: DON'T use a variable that hasn't been initialized. Results can be

  • Initialize class variable just once - objective-C 2012-04-24

    So I've been trying to get a variable in my class (TrackViewController) initialize just once. This is done to keep the inserted id from the database known to the viewcontroller. In short: I have a TrackManager which receives a location update through

  • C: Initialize module variable 2009-11-25

    I got two modules (compile units), both using a module variable with the same name: FileA.c and FileB.c both contain: #includes int m_Test; // Functions That's no problem, both variables are independent, as expected - but as soon as I assign values t

  • Is it bad practice to initialize a variable to a dummy value? 2010-05-05

    This question is a result of the answers to this question that I just asked. It was claimed that this code is "ugly" because it initializes a variable to a value that will never be read: String tempName = null; try{ tempName = buildFileName(); } catc

  • Default initialization of variables in action forms 2010-07-31

    i have made a from like : MyForm extend ActionForm{ list<Menu> MenuList=null; MyForm(){ super(); setMenuList(); //initialize menu list } } Menu object has string desciption and boolean variable for selected or not. In web page, i am iterating t

  • Why should I use constructor if I can initialize instance variable another way 2010-10-13

    Why should I use constructor to initialize instance variables while it is possible at the point of their declaration? class Frog { public int x = 4; Frog() { // Why should I use you } } --------------Solutions------------- You should use me because I

  • Why reference variable inside class always taking 4 bytes irrespect of type? (on 32-bit system) 2010-10-14

    I have below code, running on 32-bit windows, visual-studio. template <class T> class Test { public: T &ref; Test(T &x) :ref(x) {} }; int main() { cout<<"sizeof Test<int> : "<<sizeof(Test<int>)<<endl; cout

  • Initialize reference variables for many objects? 2010-10-15

    I'm having a little trouble building the grids for a Battleship game for my Java class. So far, I can easily make a for loop to add JPanel or JButton objects to the JFrame. However, my issue is that I'll need to use those Panels or Buttons again when

  • Why can't I initialize readonly variables in a initializer? 2010-12-16

    Why can't I initialize readonly variables in a initializer? The following doesn't work as it should: class Foo { public readonly int bar; } new Foo { bar=0; }; // does not work Is this due to some technical limits of the CLR? EDIT I know that new Foo

  • What is the better approach to initialize class variables? 2011-03-16

    Here are two way to initialize class variables. 1st Method class Test { private $var1; private $var2; public function Test($var1,$var1) { $this->var1 = $var1; $this->var2 = $var2; } } $objTest = new Test("value1","value2"); 2nd Method class Tes

Copyright (C) dskims.com, All Rights Reserved.

processed in 0.121 (s). 11 q(s)