构造方法何时被调用?

构造方法何时被调用?,第1张

问题一:Java中构造方法何时被调用 新建一个对象时被调用。也就是new的时候;

如:

public class A{

int i;

String c;

public A(){ } 无参构造方法

public A(int i,String c)

{

thisi = i;

thisc = c;

}两参构造方法

public static void main(String[] args){

A a = new A() ;调用了无参构造方法;

A a1 = new A(5,vieri);调用了两参构造方法

}

}

问题二:java 构造函数什么时候被调用执行 在java语言 中,构造函数又称构造方法。特殊性在于,与普通方法的区别是,他与类名相同,不返回结果也不加void返回值。构造函数的作用是初始化对象,即在创建对象时被系统调用(与普通方法不同,程序不能显示调用构造函数)。构造函数还能够被重载,即可以传入参数,当程序中包含有带参的构造函数时,系统将不会再提供的无参构造函数。构造函数特点:没有函数返回值,构造函数名与类名相同;当创建类对象的时候调用其对应的构造方法去创建。每创建一个类的实例都去初始化它的所有变量是乏味的。如果一个对象在被创建时就完成了所有的初始工作,将是简单的和简洁的。因此,Java在类里提供了一个特殊的成员函数,叫做构造函数(Constructor)。 一个构造函数是对象被创建时初始对象的成员函数。它具有和它所在的类完全一样的名字。一旦定义好一个构造函数,创建对象时就会自动调用它。构造函数没有返回类型,即使是void类型也没有。这是因为一个类的构造函数的返回值的类型就是这个类本身。构造函数的任务是初始化一个对象的内部状态,所以用new *** 作符创建一个实例后,立刻就会得到一个清楚、可用的对象。 构造方法是一种特殊的方法,具有以下特点。 (1)构造方法的方法名必须与类名相同。 (2)构造方法没有返回类型,也不能定义为void,在方法名前面不声明方法类型。(3)构造方法的主要作用是完成对象的初始化工作,它能够把定义对象时的参数传给对象的域。 (4)构造方法不能由编程人员调用,而要系统调用。 (5)一个类可以定义多个构造方法,如果在定义类时没有定义构造方法,则编译系统会自动插入一个无参数的默认构造器,这个构造器不执行任何代码。 (6)构造方法可以重载,以参数的个数,类型,或排列顺序区分。

问题三:一个类的构造函数和析构函数什么时候被调用 在对象被创建的时候就会调用构造函数,比如 声明一个类class A{},当你在main函数中

A a ; 定义一个对象a的时候, 就调用构造函数,默认构造函数都是无参数的 ,构造函数就相当给对象a初始化而已,就相当于c语言中 int a = 3 初始化a的值而已,因为你在类中是不能直接给private中的类成员赋值的,所以就靠构造函数,不过要注意有参构造和无参构造,默认都是无参的,比如你A a(1, 3)这样的就不对了 除非你在类中写一个带参数的构造函数。

当函数调用结束的时候,会自动调用析构函数,比如你在clsaa A { public:Add()},

当你A a; aAdd();后 就自动调用析构,你可以在类中 ~A{cout。。。},你就会发现调用

aAdd() 后就打出你在析构函数中写的东西,是自动调用的,析构的作用就是释放对象占用的资源。以为默认析构什么也不打印,所以你不会直观看出析构函数什么时候执行,自己在析构中加上打印的语言你就会看到了。希望对你能有所帮助

问题四:为什么说构造方法是一种特殊的方法?构造方法什么时候执行?被调用? 构造方法没有返回值,方法名和类名一样,其作用是用于在NEW一个类的时候,会总先调用这个类的构造方法,构造方法内部可以作一些变量的初始化或在创建这个类时必须调用的一些方法和运算,他是不用特意去调用的方法,会随着类的创建而自动去调用

例如:我们需要做一个i+j的运算,在这期间我们用到了构造函数,让其改变了i和j的初始化值

public class Text {

int i = 0;

int j = 0;

/

Text 的构造函数 将i和J的值重新初始化赋值

/

public Text() {

i = 1;

j = 2;

};

public static void main(String[] args) {

Text s = new Text();

此时当你NEW完Text()时程序已经自动执行了Text的构造 函数i和j的值已经是1和2

Systemoutprintln(si + sj);

}

}

问题五:构造函数何时被调用 问法还是有问题的,构造函数包括复制构造函数

对象被创建时构造函数被调用,关键词:创建时,A a; 这种形式,指针类型在new的时候才调用

复制构造函数,也是构造函数,用一个对象作为参数创建另一个对象时,或赋值(同样关注创建时)

如 A a(b);

A b;

A a = b;

以下的不是调用复制构造函数

A a,b; 默认(无参)构造被调用

a = b; 赋值

问题六:java中的构造方法到底有什么用什么时候采用 1如果当用户没有定义构造方法时,编译器会为类自动添加形如类名() { } 的无参构造方法,但是一但自己定义了构造 方法,编译器将不再自动添加

也就是说构造方法不是必须有的如果你之前一直未自定义构造方法,当你new一个对象时,系统会自动调用默认的一个无伐构造方法,给你对象的实例变量赋初值,比如int型默认为0但一旦你自己定义了构造方法并new一个对象后,你再new一个对象时系统将不再为你自动提供默认的无参构造方法,那么你必须自己定义一个构造方法,否则编译出错

2 构造器可以不只一个,这叫做方法的重载

3构造方法不但是要给对象的实例变量赋初值,更重要的是还和new一起来创建对象 ,如果你的对象没有实例变量,当然不用给对象的实例变量赋初值,也就不需要有参的构造器但这在实际应用中,是毫无意义的因为没有实例变量的对象什么也干不了

问题七:java中构造方法(类)有哪些条件,一般什么时候被调用 构造方法是类中比较特殊的方法、它有如下几个特点

1方法没有返回值

2方法名和类名相同

3构造方法可以重载(包括参数类型不同的重载和参数个数不同的重载)

4每个类默认会有一个无参的构造函数

例:

public Class User{

public User(){}

public User(String name,int age){

thisname = name;

thisage = age;

}

private String name;

private int age;

public String getName(){

return thisname;

}

public void setName(String name){

thisname = name;

}

public int getAge(){

return thisage;

}

public void setAge(int age){

thisage = age;

}

}

构造函数是在你New对象的时候被调用的

例: User user = new User();

问题八:构造方法和析构方法什么时候被调用 构造函数的作用是保证每个对象的数据成员都有何时的初始值。

析构函数的作用是回收内存和资源,通常用于释放在构造函数或对象生命期内获取的资源。

一般我们都知道构造和析构的次序:

构造从类层次的最根处开始,在每一层中,首先调用基类的构造函数,然后调用成员对象的构造函数。析构则严格按照与构造相反的次序执行,该次序是唯一的,否则编译器将无法自动执行析构过程。

构造函数和析构函数都是由编译器隐式调用的。这些函数的调用顺序取决于程序的执行进入和离开实例化对象时所在的那个作用域的顺序。一般而言,析构函数的调用顺序和构造函数的调用顺序相反,但是,对象的存储类可以改变析构函数的调用顺序。

对于在全局作用域中定义的对象,它们的构造函数是在文件中所有其他函数(包括main)开始执行之前被调用的(但无法保证不同文件的全局对象构造函数的执行顺序)。对应的析构函数是在终止main之后调用的。

exit函数会迫使程序立即终止,而不会执行自动对象的析构函数。这个函数经常用来在检测到输入错误或者程序所处理的文件无法打开时终止程序。

abort函数与exit函数功能相似,但它会迫使程序立即终止,而不允许调用任何对象的析构函数。abort函数通常用来表明程序的非正常终止。

自动局部变量的构造函数是在程序的执行到达定义这个对象的位置时调用的,而对应的析构函数是在程序离开这个对象的作用域时调用的(即定义这个对象的代码完成了执行)。每次执行进入和离开自动对象的作用域时,都会调用它的构造函数和析构函数。如果程序调用了exit或abort函数而终止,则不会调用自动对象的析构函数。

静态局部对象的析构函数只调用一次,即执行首次到达定义这个对象的位置时。对应的析构函数是在main终止或程序调用exit函数时调用的。

全局对象和静态对象是以创建它们时相反的顺序销毁的。如果程序由于调用了exit函数而终止,则不会调用静态对象的析构函数。

下面的demo演示了在几个作用域不同的存储类的CreateAndDestory的类的对象,它们的构造函数和析构函数的调用顺序。

[cpp] view plaincopy

#include

#include

using namespace std;

class Demo

{

public:

Demo(int,string); 构造函数

~Demo(); 析构函数

private:

int objectID; ID number for object

string message; message describing object

};

Demo::Demo(int ID,string messagestring)

{

objectID = ID; set object's ID number

message = messagestring; set object's descriptive message

cout>

问题九:C++构造函数什么时候会被调用? Point的构造函数被调唬两次,你可以这么理解:

当你要构造一个Rect对象的时候,每个Rect对象是不是包含两个Point对象?

所以这就是为啥构造两次的原因了。

析构与构造是一样的,两次释放,每个Point分别被析构一次。

js中的函数有两种调用方式,一种是通过普通的声明之后进行的调用。一种是通过new关键字进行构造调用。普通的调用就是依次执行函数内部的函数语句,如果有返回值则返回返回值,如果没有则函数内部的声明周期结束。但是,函数还有另一个调用方式,使用new关键字,将函数当做构造函数。js中没有所谓独立出来的构造函数的概念,所有的函数都用同样的方式声明,所以有了new这个关键字,js(ES6之前)只能通过这种方式实现构造器的构造。那么使用new关键字跟普通的调用有什么区别呢?

使用new关键字,比普通的函数调用,主要分为以下四个步骤:

稍后我们会对上面的四句话逐一解析,首先我们看一看函数调用的两种方式:

这样看来,两者似乎没有区别,但是这里要注意,使用new进行构造调用时,函数是有返回值的。

上面的return2并没有返回一个函数。

其实它会返回一个空的对象。这也就是上面使用new关键词的第一步, 内部创建一个新的空对象

那么当函数内部有this时,结果会是怎样的呢?

使用new关键字后,在函数内部如果出现了this,则自动将this指向内部新建的对象上。最后返回时,因为this的缘故,对象上新建了a属性,并且赋值返回。

修正定义的对象Object的[[prototype]]

虽然实例上的[[prototype]]属性__proto__是ES6才作为规范出版的。但是在这之前chrome已经支持__proto__属性,他指向对象的原型。

原型的问题相当复杂,单独拿出来也可以当好几篇文章的量来讲。但是这并不是本文的重点。但是每一个对象从根部来说,继承自Object。而Objectprototype上面定义了一些方法,有类似toString,valueOf等等等方法。对于对象来说,支持通过属性链和方法链向上查询。所以在一个对象实例中,如果没有定义toString方法,但它还可以向上查询,找到原型中的toString方法,进行调用。

同时的,有很多元素通过Object实现继承。比如Function, Array, RegExp等等对象,它们也是对象,但是却是继承来自Object。

在这里,内部定义的对象,让他继承来自构造函数。

最后一步,也是最容易被忽略的一步,那就是当构造函数存在返回值时,并且返回值为对象时,返回对象而不返回之前定义的对象。

当然,上面说的Function,Array,RegExp也算Object的一种,如果返回他们同样也会阻止默认的对象返回。

 摘 要:构造函数与析构函数是一个类中看似较为简单的两类函数,但在实际运用过程中总会出现一些意想不到的运行错误。本文将较系统的介绍构造函数与析构函数的原理及在C#中的运用,以及在使用过程中需要注意的若干事项。

 关键字:构造函数;析构函数;垃圾回收器;非托管资源;托管资源

  一.构造函数与析构函数的原理

 作为比C更先进的语言,C#提供了更好的机制来增强程序的安全性。C#编译器具有严格的类型安全检查功能,它几乎能找出程序中所有的语法问题,这的确帮了程序员的大忙。但是程序通过了编译检查并不表示错误已经不存在了,在“错误”的大家庭里,“语法错误”的地位只能算是冰山一角。级别高的错误通常隐藏得很深,不容易发现。

 根据经验,不少难以察觉的程序错误是由于变量没有被正确初始化或清除造成的,而初始化和清除工作很容易被人遗忘。微软利用面向对象的概念在设计C#语言时充分考虑了这个问题并很好地予以解决:把对象的初始化工作放在构造函数中,把清除工作放在析构函数中。当对象被创建时,构造函数被自动执行。当对象消亡时,析构函数被自动执行。这样就不用担心忘记对象的初始化和清除工作。

  二.构造函数在C#中的运用

 构造函数的名字不能随便起,必须让编译器认得出才可以被自动执行。它的命名方法既简单又合理:让构造函数与类同名。除了名字外,构造函数的另一个特别之处是没有返回值类型,这与返回值类型为void的函数不同。如果它有返回值类型,那么编译器将不知所措。在你可以访问一个类的方法、属性或任何其它东西之前, 第一条执行的语句是包含有相应类的构造函数。甚至你自己不写一个构造函数,也会有一个缺省构造函数提供给你。

 class TestClass

 {

 public TestClass(): base() {} // 由CLR提供

 }

 下面列举了几种类型的构造函数

 1)缺省构造函数

 class TestClass

 {

 public TestClass(): base() {}

 }

 上面已介绍,它由系统(CLR)提供。

 2)实例构造函数

 实例构造函数是实现对类中实例进行初始化的方法成员。如:

 using System;

 class Point

 {

 public double x, y;

 public Point()

 {

 thisx = 0;

 thisy = 0;

 }

 public Point(double x, double y)

 {

 thisx = x;

 thisy = y;

 }

 }

 class Test

 {

 static void Main()

 {

 Point a = new Point();

 Point b = new Point(3, 4); // 用构造函数初始化对象

 }

 }

 声明了一个类Point,它提供了两个构造函数。它们是重载的。一个是没有参数的Point构造函数和一个是有两个double参数的Point构造函数。如果类中没有提供这些构造函数,那么会CLR会自动提供一个缺省构造函数的。但一旦类中提供了自定义的构造函数,如Point()和Point(double x, double y),则缺省构造函数将不会被提供,这一点要注意。

 3) 静态构造函数

 静态构造函数是实现对一个类进行初始化的方法成员。它一般用于对静态数据的初始化。静态构造函数不能有参数,不能有修饰符而且不能被调用,当类被加载时,类的静态构造函数自动被调用。如:

 using SystemData;

 class Employee

 {

 private static DataSet ds;

 static Employee()

 {

 ds = new DataSet();

 }

 }

 声明了一个有静态构造函数的类Employee。注意静态构造函数只能对静态数据成员进行初始化,而不能对非静态数据成员进行初始化。但是,非静态构造函数既可以对静态数据成员赋值,也可以对非静态数据成员进行初始化。

 如果类仅包含静态成员,你可以创建一个private的构造函数:private TestClass() {…},但是private意味着从类的外面不可能访问该构造函数。所以,它不能被调用,且没有对象可以被该类定义实例化。

 以上是几种类型构造函数的简单运用,下面将重点介绍一下在类的层次结构中(即继承结构中)基类和派生类的构造函数的使用方式。派生类对象的初始化由基类和派生类共同完成:基类的成员由基类的构造函数初始化,派生类的成员由派生类的构造函数初始化。

 当创建派生类的对象时,系统将会调用基类的构造函数和派生类的构造函数,构 造函数的执行次序是:先执行基类的构造函数,再执行派生类的构造函数。如果派生类又有对象成员,则,先执行基类的构造函数,再执行成员对象类的构造函数,最后执行派生类的构造函数。

 至于执行基类的什么构造函数,缺省情况下是执行基类的无参构造函数,如果要执行基类的有参构造函数,则必须在派生类构造函数的成员初始化表中指出。如:

 class A

 { private int x;

 public A( ) { x = 0; }

 public A( int i ) { x = i; }

 };

 class B : A

 { private int y;

 public B( ) { y = 0; }

 public B( int i ) { y = i; }

 public B( int i, int j ):A(i) { y = j; }

 };

 B b1 = new B(); //执行基类A的构造函数A(),再执行派生类的构造函数B()

 B b2 = new B(1); //执行基类A的构造函数A(),再执行派生类的构造函数B(int)

 B b3 = new B(0,1); //执行执行基类A的构造函数A(int) ,再执行派生类的

 构造函数B(int,int)

 在这里构造函数的执行次序是一定要分析清楚的。另外,如果基类A中没有提供无参构造函数public A( ) { x = 0; },则在派生类的所有构造函数成员初始化表中必须指出基类A的有参构造函数A(i),如下所示:

 class A

 { private int x;

 public A( int i ) { x = i; }

 };

 class B : A

 { private int y;

 public B():A(i) { y = 0; }

 public B(int i):A(i) { y = i; }

 public B(int i, int j):A(i) { y = j; }

 };

  三.析构函数和垃圾回收器在C#中的运用

 析构函数是实现销毁一个类的实例的方法成员。析构函数不能有参数,不能任何修饰符而且不能被调用。由于析构函数的目的与构造函数的相反,就加前缀‘~’以示区别。

 虽然C#(更确切的说是CLR)提供了一种新的内存管理机制---自动内存管理机制(Automatic memory management),资源的释放是可以通过“垃圾回收器” 自动完成的,一般不需要用户干预,但在有些特殊情况下还是需要用到析构函数的,如在C#中非托管资源的释放。

 资源的释放一般是通过"垃圾回收器"自动完成的,但具体来说,仍有些需要注意的地方:

 1 值类型和引用类型的引用其实是不需要什么"垃圾回收器"来释放内存的,因为当它们出了作用域后会自动释放所占内存,因为它们都保存在栈(Stack)中;

 2 只有引用类型的引用所指向的对象实例才保存在堆(Heap)中,而堆因为是一个自由存储空间,所以它并没有像"栈"那样有生存期("栈"的元素d出后就代表生存期结束,也就代表释放了内存),并且要注意的是,"垃圾回收器"只对这块区域起作用;

 然而,有些情况下,当需要释放非托管资源时,就必须通过写代码的方式来解决。通常是使用析构函数释放非托管资源,将用户自己编写的释放非托管资源的代码段放在析构函数中即可。需要注意的是,如果一个类中没有使用到非托管资源,那么一定不要定义析构函数,这是因为对象执行了析构函数,那么"垃圾回收器"在释放托管资源之前要先调用析构函数,然后第二次才真正释放托管资源,这样一来,两次删除动作的花销比一次大多的。下面使用一段代码来示析构函数是如何使用的:

 public class ResourceHolder

 {

 ~ResourceHolder()

 {

 // 这里是清理非托管资源的用户代码段

 }

 }

  四.小结

 构造函数与析构函数虽然是一个类中形式上较简单的函数,但它们的使用决非看上去那么简单,因此灵活而正确的使用构造函数与析构函数能够帮你更好的理解CLR的内存管理机制,以及更好的管理系统中的资源。

  每个类只有一个赋值函数

  一般情况下,对于任意一个类A,如果程序员不显示的声明和定义上述函数,C++编译器将会自动的为A产生4个public inline 的默认函数,这4个函数最常见的形式为:

  A() //默认构造函数

  A(const A&) //默认拷贝构造函数

  ~A() //默认析构函数

  A& operator = (const A &) //默认赋值函数。

  由于并非所有的对象都会使用拷贝构造函数和赋值函数,程序员可能对这两个函数有些轻视。请先记住以下的警告,在阅读正文时就会多心:

  如果不主动编写拷贝构造函数和赋值函数,编译器将以“位拷贝”的方式自动生成缺省的函数。倘若类中含有指针变量,那么这两个缺省的函数就隐含了错误。以类String的两个对象a,b为例,假设am_data的内容为“hello”,bm_data的内容为“world”。

  现将a赋给b,缺省赋值函数的“位拷贝”意味着执行bm_data = am_data。这将造成三个错误:一是bm_data原有的内存没被释放,造成内存泄露;二是bm_data和am_data指向同一块内存,a或b任何一方变动都会影响另一方;三是在对象被析构时,m_data被释放了两次。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/12188570.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存