2
    class Base{};
    class Derived: public Base{};

    int main()
    {
        Base B;
        Derived D;

        Base B1 = D;//OK
        Derived D1 = B;//error: conversion from ‘Base’ to non-scalar 
                       //type ‘Derived’ requested
        return 1;
    }

I know derived class has a is-a relationship with base class.

What stops the Derived D1 having values from B and remaining member variables(if any) with some garbage value?

Or

What does the error message

conversion from ‘Base’ to non-scalar type ‘Derived’ requested Derived D1 = B;

say? What is a scalar type?

Sreeraj Chundayil
  • 5,548
  • 3
  • 29
  • 68
  • You might add the constructor `Derived(const Base&)` to provide the conversion –  Jan 14 '15 at 18:20
  • The "is-a" relationship only works in one direction. – Mark Ransom Jan 14 '15 at 18:20
  • Ok, But my question was , why not by default. – Sreeraj Chundayil Jan 14 '15 at 18:21
  • The answer is in the question. Garbage values. – Oktalist Jan 14 '15 at 18:21
  • This is not an exact duplicate, previous question was about copy assignment, and no one talks about initialization. – Sreeraj Chundayil Jan 14 '15 at 18:26
  • The derived to base conversion can be implicit. A derived class consists of a base class *suboject*. `Base B1 = D` means to initialize `B1` by copying the `Base` subobject from `D` into `B1`. The base to derived conversion is not implicit. A `Base` class does not contain its derived class object, only the other way around. However, if you have a reference or pointer to a `Base` class, you can explicitly cast through `static_cast` if you know its dynamic type is a `Derived` class or `dynamic_cast` (if you aren't sure) to get the pointed-to (or referred-to) derived object. – David G Jan 14 '15 at 18:29
  • As for what a scalar is, see http://stackoverflow.com/questions/14821936/what-is-a-scalar-object-in-c – David G Jan 14 '15 at 18:30

2 Answers2

5

The statement

Derived D1 = B;

is an initialization, not an assignment (even if it looks like an assignment).

It attempts to use the Derived copy constructor, but that copy constructor takes an argument Derived const&. And the B instance can't be automatically converted down to a full Derived.

If you really want a slice assignment – assigning only to the Base slice of D1 – then you can explicitly use the Base::operator=:

Derived D1;
D1.Base::operator=( B );

Another way to express that:

Derived D1;
static_cast<Base&>( D1 ) = B;

But it smells bad. ;-)


Re

What is a scalar type?

That's the same word as in “scale”. A scalar type provides a single magnitude value, so that values of the type can be compared with == (and ideally also <). However, in C++ pointers and even member pointers are regarded as scalar types:

C++11 §3.9/9 [basic.types]:

Arithmetic types (3.9.1), enumeration types, pointer types, pointer to member types (3.9.2), std::nullptr_t, and cv-qualified versions of these types (3.9.3) are collectively called scalar types.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
0

If B's member variables are declared private, then that would stop D1 from having B's values.

As far as your second question, You can assign Base B1 = D; because the compiler knows D is a derived class from B. However, in Derived D1 = B;, the compiler has no indication of that relationship.

As far as to your question of what a scalar is, scalars are ints, chars, pointers, etc. They are different from structs and classes, which are user-defined types.

Lawrence Aiello
  • 4,560
  • 5
  • 21
  • 35