inheritance and casting

Hey guys,

I'm following a Jamie king video on youtube (https://www.youtube.com/watch?v=TFwW36dLoHY ) about inheritance and casting, I'm still not quite sure of the action of the terenary operator here, why couldn't we do -

Base* b = (rand() % 2 == 0) ? new Derived1 : new Derived2;

when this is done the compiler throws a compile time error saying:

error: conditional expression between distinct pointer types 'Derived1*' and 'Derived2*' lacks a cast|

so why do we need to convert the new Derived1 to a base pointer in the first place and more importantly how come we only need to do it on one of the returning objects

for example this code works fine
Base* b = (rand() % 2 == 0) ? static_cast<Base*>(new Derived1): new Derived2;

as above we only needed to cast Derived1 and not Derived2, how come?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

#include <iostream>
#include <time.h>
#include <stdlib.h>

using namespace std;

class Base{

    virtual void f(){}
};

class Derived1 : public Base{
};

class Derived2 : public Base{
};

int main()
{
   srand(time(0));

   Base* b = (rand() % 2 == 0) ? static_cast<Base*>(new Derived1): new 
   Derived2;
}


side question: why is it when you introduce a virtual function to a class when using polymorphism that class will be of the type of that class but when you don't have a virtual function in the base class the type of class will be it's base class?

and why do you only need to introduce a virtual function for this to work? I thought you would need a virtual constructor?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32


#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <typeinfo>

using namespace std;

class Base{

   virtual void f(){}
};

class Derived1 : public Base{
};

class Derived2 : public Base{
};

int main()
{


   Base* b = new Derived1;
   cout << typeid(*b).name() << endl; // with virtual function in the class 
                                      // prints derived1.
                                   
                // without virtual function in base class prints base
}



thanks
Last edited on
Base* b = (rand() % 2 == 0) ? new Derived1 : new Derived2; can be rewritten as:

23
24
25
26
27
28
29
30
31
32
   Base* b;

   if (rand() % 2 == 0)
   {
      b = new Derived1;
   }
   else
   {
      b = new Derived2;
   }

You should learn how to use the C++ libraries <random> and <chrono> for obtaining random numbers. The C library is really limited.

Getting random numbers from the C++ libraries isn't as neat and easy as the C library functions, but yield much better results.

The usage in your code is rather trivial, it basically flips a coin. When you start generating random numbers with different ranges is when the C++ approach will be helpful.

http://www.cplusplus.com/reference/random/linear_congruential_engine/linear_congruential_engine/
The conditional/ternary (?:) operator is more restrictive than if-else when it comes to working with multiple types.

https://en.cppreference.com/w/cpp/language/operator_other
3) Otherwise, if E2 and E3 have different types, at least one of which is a (possibly cv-qualified) class type, or both are glvalues of the same value category and have the same type except for cv-qualification, then an attempt is made to form an implicit conversion sequence

https://en.cppreference.com/w/cpp/language/implicit_conversion

I'm not going to pretend I really understand the language used there... but (a ? b : c) is an lvalue if b and c are the same type. Otherwise, it becomes an rvalue, in this case. It attempts to do some sort of conversion between the two pointers, but converting from one derived pointer to another type of derived pointer isn't legal, so the conversion fails, and it doesn't compile. That's what I think is happening anyway.

I generally would avoid using ?: operator if b and c are different types.
Last edited on
Topic archived. No new replies allowed.