A constructor is an optional function that is executed upon contract creation.
No functions, including the receive() function, can be invoked from logic in the constructor. Only logic and calls inside the constructor will execute as expected.
An unexpected consequence of this is if a call is made in the constructor that results in ETH being sent to the receive() function, as the ETH does get received, but the logic in the receive() function doesn't execute.
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;// Base contract Xcontract X {stringpublic name;constructor(stringmemory_name) { name = _name; }}// Base contract Ycontract Y {stringpublic text;constructor(stringmemory_text) { text = _text; }}// There are 2 ways to initialize parent contract with parameters.// Pass the parameters here in the inheritance list.contractBisX("InputtoX"), Y("InputtoY") {}contractCisX, Y {// Pass the parameters here in the constructor,// similar to function modifiers.constructor(stringmemory_name,stringmemory_text) X(_name) Y(_text) {}}// Parent constructors are always called in the order of inheritance// regardless of the order of parent contracts listed in the constructor of the child contract.// Order of constructors called:// 1. X// 2. Y// 3. DcontractDisX, Y {constructor() X("X was called") Y("Y was called") {}}// Order of constructors called:// 1. X// 2. Y// 3. EcontractEisX, Y {constructor() Y("Y was called") X("X was called") {}}