|
1 | 1 | ---
|
2 | 2 | title: "Constructors (C++)"
|
3 |
| -ms.date: "11/19/2019" |
| 3 | +ms.date: "12/27/2019" |
4 | 4 | helpviewer_keywords: ["constructors [C++]", "objects [C++], creating", "instance constructors"]
|
5 | 5 | ms.assetid: 3e9f7211-313a-4a92-9584-337452e061a9
|
6 | 6 | ---
|
@@ -469,6 +469,52 @@ If a constructor throws an exception, the order of destruction is the reverse of
|
469 | 469 |
|
470 | 470 | 1. If the constructor is non-delegating, all fully-constructed base class objects and members are destroyed. However, because the object itself is not fully constructed, the destructor is not run.
|
471 | 471 |
|
| 472 | +## <a name="extended_aggregate"></a> Derived constructors and extended aggregate initialization |
| 473 | +
|
| 474 | +If the constructor of a base class is non-public, but accessible to a derived class, then under **/std:c++17** mode in Visual Studio 2017 version 15.7 and later you can't use empty braces to initialize an object of the derived type. |
| 475 | +
|
| 476 | +The following example shows C++14 conformant behavior: |
| 477 | +
|
| 478 | +```cpp |
| 479 | +struct Derived; |
| 480 | +
|
| 481 | +struct Base { |
| 482 | + friend struct Derived; |
| 483 | +private: |
| 484 | + Base() {} |
| 485 | +}; |
| 486 | +
|
| 487 | +struct Derived : Base {}; |
| 488 | +
|
| 489 | +Derived d1; // OK. No aggregate init involved. |
| 490 | +Derived d2 {}; // OK in C++14: Calls Derived::Derived() |
| 491 | + // which can call Base ctor. |
| 492 | +``` |
| 493 | + |
| 494 | +In C++17, `Derived` is now considered an aggregate type. It means that the initialization of `Base` via the private default constructor happens directly, as part of the extended aggregate initialization rule. Previously, the `Base` private constructor was called via the `Derived` constructor, and it succeeded because of the friend declaration. |
| 495 | + |
| 496 | +The following example shows C++17 behavior in Visual Studio 2017 version 15.7 in **/std:c++17** mode: |
| 497 | + |
| 498 | +```cpp |
| 499 | +struct Derived; |
| 500 | + |
| 501 | +struct Base { |
| 502 | + friend struct Derived; |
| 503 | +private: |
| 504 | + Base() {} |
| 505 | +}; |
| 506 | + |
| 507 | +struct Derived : Base { |
| 508 | + Derived() {} // add user-defined constructor |
| 509 | + // to call with {} initialization |
| 510 | +}; |
| 511 | + |
| 512 | +Derived d1; // OK. No aggregate init involved. |
| 513 | + |
| 514 | +Derived d2 {}; // error C2248: 'Base::Base': cannot access |
| 515 | + // private member declared in class 'Base' |
| 516 | +``` |
| 517 | +
|
472 | 518 | ### Constructors for classes that have multiple inheritance
|
473 | 519 |
|
474 | 520 | If a class is derived from multiple base classes, the base class constructors are invoked in the order in which they are listed in the declaration of the derived class:
|
|
0 commit comments