为什么要构造无参构造函数

一个类 被实例化 也就是被new的时候 最先执行的是 构造函数,如果你有留心。你会发现很多类里面根本没有写构造函数。
在java类中,如果不显示声明构造函数,JVM 会给该类一个默认的构造函数。一个类 可以有多个构造函数。构造函数的主要作用 一是用来实例化该类。二是 让该类实例化的时候执行哪些方法,初始化哪些属性。当一个类声明了构造函数以后,JVM 是不会再给该类分配默认的构造函数。
比如一个实体类
public class entity{
private int id;
private String userName;
get…set..方法
}
如果这样写该类就是默认的构造函数。该类实例化的时候 id 和 username 就是默认值 即 id=0,username=null.
如果在里面加入这样一个方法
public entity(int id,String userName){
调用get..set..
}
如果这样写 该类实例化的时候 必须给出 id 和username参数。 JVM不会再给这个类默认构造函数
你也可以理解成 在没有给构造函数的时候 JVM 给你的类加了一个这样的函数
public entity(){
this.id=0;
this.userName=null;
}
其实构造函数是用来对一个类以及变量进行实例化。
构造方法,在new对象的时候就会自己调用,也是对象的初始方法,如果你自己不写构造方法默认的会自动加上一个无参的构造。如果不存在构造方法那也就创建不了类的实例。
public class Test {
private String name;
private String sex;
private String age;
public Test(){
super();
}
public Test(String name){
this.name=name;
}
public Test(String name,String sex){
this.name=name;
this.sex=sex;
}
public Test(String name,String sex,String age){
this.name=name;
this.sex=sex;
this.age=age;
}
}
上面写了一个简单的类,一共有四个构造方法,这样你就有四种方法构造类实例(对象)
new Test();
new Test(“张三”);
new Test(“张三”,”男”);
new Test(“张三”,”男”,”16”);
有了构造,也就相应提供了初始方法

<think>我们正在讨论的是:派生类使用无构造函数时,如何初始化基类的public成员变量。 根据之前的讨论,我们知道: 1. 派生类不能直接在初始化列表中初始化基类的成员变量(即使是public的),因为基类成员变量不属于派生类的直接成员[^3]。 2. 初始化基类成员变量的正确方式是通过调用基类的构造函数(在派生类构造函数的成员初始化列表中)[^1][^3]。 因此,当派生类使用无构造函数时,我们需要考虑两种情况: 情况1:基类有无构造函数(默认构造函数) 情况2:基类没有无构造函数 对于情况1(基类有无构造函数): - 如果派生类使用无构造函数,并且没有在初始化列表中显式调用基类构造函数,那么编译器会自动调用基类的无构造函数。 - 基类的无构造函数会初始化基类的public成员变量(按照基类无构造函数的实现)。 对于情况2(基类没有无构造函数): - 如果基类没有无构造函数,那么派生类的无构造函数必须在初始化列表中显式调用基类的某个带数的构造函数,否则编译失败。 下面用代码示例说明两种情况: 情况1示例(基类有无构造函数): ```cpp #include <iostream> using namespace std; class Base { public: int publicVar; // public成员变量 Base() : publicVar(0) { // 基类的无构造函数,将publicVar初始化为0 cout << "Base default constructor: publicVar = " << publicVar << endl; } }; class Derived : public Base { public: // 派生类的无构造函数,没有显式调用基类构造函数,编译器会自动调用Base() Derived() { cout << "Derived default constructor: publicVar = " << publicVar << endl; } }; int main() { Derived d; // 调用派生类无构造函数 cout << "d.publicVar = " << d.publicVar << endl; // 输出0 return 0; } ``` 输出: Base default constructor: publicVar = 0 Derived default constructor: publicVar = 0 d.publicVar = 0 情况2示例(基类没有无构造函数): ```cpp #include <iostream> using namespace std; class Base { public: int publicVar; Base(int val) : publicVar(val) { // 基类只有带数的构造函数,没有无构造函数 cout << "Base constructor with parameter: " << publicVar << endl; } }; class Derived : public Base { public: // 派生类的无构造函数,必须显式调用基类的构造函数 // 这里我们调用基类的带构造函数,并传入一个默认值(比如100) Derived() : Base(100) { // 显式调用基类构造函数 cout << "Derived default constructor: publicVar = " << publicVar << endl; } }; int main() { Derived d; cout << "d.publicVar = " << d.publicVar << endl; // 输出100 return 0; } ``` 输出: Base constructor with parameter: 100 Derived default constructor: publicVar = 100 d.publicVar = 100 如果情况2中派生类无构造函数没有显式调用基类构造函数,则编译错误: ```cpp class Derived : public Base { public: Derived() { // 错误:Base类没有可用的默认构造函数 // ... } }; ``` 总结: 1. 当派生类使用无构造函数时,基类的public成员变量是通过基类的构造函数来初始化的。 2. 如果基类提供了无构造函数(默认构造函数),那么派生类无构造函数可以不显式调用基类构造函数(编译器自动调用)。 3. 如果基类没有无构造函数,则派生类无构造函数必须在初始化列表中显式调用基类的某个构造函数(并传递所需数)。 注意:即使基类的成员变量是public的,也不应该在派生类构造函数的函数体内用赋值语句来初始化(虽然可以赋值,但这不是初始化,而且基类部分已经被构造了,先调用了基类构造函数,再进入派生类构造函数体,所以实际上是先初始化再赋值,效率较低,且如果基类没有默认构造函数则无法通过编译)[^3]。 因此,始终推荐通过调用基类构造函数来初始化基类成员变量(包括public成员变量)[^1][^3]。 相关问题: 1. 如果基类没有默认构造函数,派生类如何编写无构造函数? 2. 派生类无构造函数中调用基类带构造函数数如何确定? 3. 基类成员变量为public时,在派生类无构造函数体内赋值和通过基类构造函数初始化有什么区别? 4. 基类成员变量为private时,派生类如何初始化基类成员变量? 5. 多继承情况下,派生类无构造函数如何初始化多个基类的成员变量?</think>### 派生类无构造函数初始化基类 public 成员变量的方法 当派生类使用无构造函数时,初始化基类 public 成员变量的方式取决于基类构造函数的定义: #### 情况1:基类有默认构造函数(无构造函数) ```cpp class Base { public: int publicVar; // public 成员变量 Base() : publicVar(0) { // 基类默认构造函数 cout << "Base default constructor" << endl; } }; class Derived : public Base { public: // 派生类无构造函数 Derived() { cout << "Derived constructor" << endl; } }; ``` **执行过程**: 1. 创建 `Derived` 对象时自动调用基类 `Base` 的默认构造函数 2. 基类构造函数初始化 `publicVar = 0` 3. 然后执行派生类构造函数体 #### 情况2:基类没有默认构造函数 ```cpp class Base { public: int publicVar; Base(int val) : publicVar(val) {} // 基类只有带构造函数 }; class Derived : public Base { public: // 必须显式调用基类构造函数 Derived() : Base(100) { // 通过初始化列表调用基类构造函数 cout << "publicVar = " << publicVar << endl; // 输出100 } }; ``` **执行过程**: 1. 在派生类构造函数的初始化列表中显式调用基类构造函数 `Base(100)` 2. 基类构造函数初始化 `publicVar = 100` 3. 然后执行派生类构造函数体 ### 关键原则 1. **自动调用机制**: - 当派生类构造函数**没有显式调用**基类构造函数时,编译器会**自动调用基类的默认构造函数**[^1][^4] - 如果基类没有默认构造函数,必须**显式调用**基类的其他构造函数[^3] 2. **初始化顺序**: - 基类构造函数先执行 - 派生类成员初始化 - 派生类构造函数体执行[^1] ```mermaid graph LR A[创建派生类对象] --> B[调用基类构造函数] B --> C[初始化基类成员] C --> D[初始化派生类成员] D --> E[执行派生类构造函数体] ``` 3. **错误用法示例**: ```cpp class Derived : public Base { public: Derived() { publicVar = 5; // 错误!先调用默认构造再赋值 } }; ``` - 如果基类没有默认构造函数,此代码会导致编译错误 - 即使基类有默认构造函数,也会先初始化再赋值,效率低下[^3] ### 最佳实践 1. **始终通过初始化列表调用基类构造函数**,即使基类成员是 public 的: ```cpp // 正确方式 Derived() : Base(initial_value) { ... } ``` 2. **避免在构造函数体内赋值**: - 可能导致二次赋值(先默认初始化再修改) - 基类无默认构造函数时无法编译[^3] 3. **多基类处理**: ```cpp class Derived : public Base1, public Base2 { public: Derived() : Base1(val1), Base2(val2) {} }; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值