0

Im trying to cast class, but something is wrong. I was trying static_cast<>, dynamic_cast<> but still im getting errors. I need one array with 2 types of classes.

class user
{
  int value;
  user(int valueInit) 
  {
     value = valueInit;
  };

  int getValue()
  {
     return value;
  }

};

class premium : public user
{
  int premiumValue;
  premium(int valueInt, int premiumValueInit) 
  {
      value = valueInt;
      premiumValue = premiumValueInit;
  };
};

And here is main code in main() function

user fUser(10);
premium fPremium(20, 5);

premium *array = new premium[2];

(user)array[0] = u1;
array[1] = p1;

cout << "Value: " << array[0].getValue() << endl; //incorrect/random value
    cout << "Value: " << array[1].getValue() << endl; //correct value

Usually I use java, so I have huge problems with c++. I know what I should do but I dont know how.

Jakub Pomykała
  • 2,082
  • 3
  • 27
  • 58

1 Answers1

1

The why

The problem with your cast, (user)array[0] = u1 is that it is, theoretically, equivalent to the code below:

{
  user unnamed_instance = array[0];
       unnamed_instance = u1;
}

In (T)a = b; an unnamed temporary will be created having type T which is than initialized with the value of b. You are assigning to this unnamed temporary, not to a.

Note: In this case slicing takes place, ie. the value in array[0], which has type premium, will be sliced into a user.


The solution

If you'd like to treat the value in array[0] as being of type user without introducing a temporary you will need to use either pointers or references. The below will correctly assign u1 to array[0] as if array[0] was of type user.

// using a reference 

static_cast<user&> (array[0]) = u1;

// using a pointer

user * ptr = static_cast<user*> (&array[0]);
      *ptr = u1;    
Community
  • 1
  • 1
Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
  • Works great, I know now what I was doing wrong: `static_cast(array[0]) = u1;` It's been a long time since I've used pointers and reference. Thanks. – Jakub Pomykała Mar 16 '14 at 23:22
  • 1
    anyone wanna explain the downvote that just got cast? – Filip Roséen - refp Mar 16 '14 at 23:40
  • If `array[0]` is of type `user`, then it is simply impossible to store a `premium` in it. Both of Filip's suggestions slice the `premium` down to `user`, but then there is no way to get the `premium` back. – M.M Mar 16 '14 at 23:41
  • 1
    The original question doesn't say anything about slicing, and he is creating an array of `premium` (not an array of `user`). – M.M Mar 16 '14 at 23:45
  • You say "lvalue in array[0]" but that is not correct usage. An lvalue is a category of **expression**, not a property of an object. The expression `array[0]` is an lvalue because it designates an object. Where you wrote *lvalue* you meant *object*. – M.M Mar 17 '14 at 00:10
  • BTW, OP's classes only have private constructors so they can't be created, and since there is no default constructor, you can't even dynamically allocate an array of them. Further, a `premium` can't be created because `base` has no default constructor and it does not pass anything to `base`'s constructor. So there must be more to this story than we're seeing. – M.M Mar 17 '14 at 00:11
  • "value yield in the expression array[0] is an lvalue" - this isn't right. An lvalue is a category of expression, not a category of value. See section [basic.lval] of the Standard. But this has nothing to do with OP's question now. – M.M Mar 17 '14 at 00:26
  • OP seems happy with your answer, I guess he will post again when he comes to add another class derived from `base`..:) – M.M Mar 17 '14 at 00:29
  • 1
    @MattMcNabb I'm in no mood to answer to nitpicking, the intent with the sentence was clear (and not using Standard terms was to keep it easier for a novice (as is what we are dealing with) to understand). Please submit your own answer to aid OP if you are certain that this will lead to follow-up questions. For your sake I will update the answer. – Filip Roséen - refp Mar 17 '14 at 00:35