精华内容
参与话题
问答
  • 构造方法的作用和用法(对于刚接触的学员)

    千次阅读 多人点赞 2018-03-14 15:38:04
    很多新学员不知道构造方法是做什么的,有的稀里糊涂,那什么是构造方法呢?先来理解一下构造方法的意思。 构造方法是一种特殊的方法,它是一个与类同名且没有返回值类型的方法。对象的创建就是通过构造方法来完成,...

    很多新学员不知道构造方法是做什么的,有的稀里糊涂,那什么是构造方法呢?先来理解一下构造方法的意思。

    构造方法是一种特殊的方法,它是一个与类同名且没有返回值类型方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法和其他方法一样也可以重载。

    看到这里有很少同学还是不懂,先理解与类同名且没有返回值类型方法

     

    那么下来理解对象的创建就是通过构造方法来完成:

     

    特殊性

     

    ​构造方法是一种特殊的成员方法,它的特殊性反映在如下几个方面:

    1.构造方法作用:(1).构造出来一个类的实例 (2).对构造出来一个类的实例(对象)初始化。

    2.构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连void也没有。

    3.主要完成对象的初始化工作,构造方法的调用是在创建一个对象时使用new操作进行的。

    4.类中必定有构造方法,若不写,系统自动添加无参构造方法。接口不允许被实例化,所以接口中没有构造方法。

    5.不能被static、final、synchronized、abstract和native修饰。

    6.构造方法在初始化对象时自动执行,一般不能显式地直接调用.当同一个类存在多个构造方法时,java编译系统会自动按照初始化时最后面括号的参数个数以及参数类型来自动一一对应。完成构造函数的调用。

    7.构造方法分为两种:无参构造方法 有参构造方法

    构造方法可以被重载。没有参数的构造方法称为默认构造方法,与一般的方法一样,构造方法可以进行任何活动,但是经常将他设计为进行各种初始化活动,比如初始化对象的属性。

    8.构造代码块:

    (1)作用:给对象进行初始化,对象一建立就执行,而且优先于构造函数执行

    (2)构造代码块和构造函数的区别:

    构造代码块是给所有不同对象的共性进行统一初始化,构造函数是给对应的对象进行初始化

    9.子类继承父类中,

    ***子类的实例化过程

    ***构造方法不能被子类继承

    ***子类创建对象时,会先去创建父类的对象。

    默认是去调用父类的无参构造方法。

    ***子类构造方法中,第一行默认是super()

    ***为什么子类中第一行会默认有super()

    因为他继承父类的成员使用,使用前这些成员必须初始化,

    而他们是父类的成员,所以,必须通过父类进行初始化。

    所以,会先创建一个父类的对象。

    **当父类没有无参构造方法时

    必须使用this或者super调用其他的构造方法。

    10.自定义类中,如果不写构造方法,java系统会默认添加一个无参的构造方法。如果写了一个有参的构造方法,就一定要写无参构造方法。

    如果想使用无参的构造方法,就必须手动给出无参构造方法。

    建议:一般情况下,我们自定义的类都要手动给出无参构造方法。

     

    展开全文
  • System.out.println("构造函数"); } { System.out.println("构造快"); } static { System.out.println("静态块"); } } 运行试试,看看会打印出什么,哈哈 public class Demo { public static void main...

    咋们话不多说,直接上代码

    class A{
        A(){
            System.out.println("构造函数");
        }
        {
            System.out.println("构造快");
        }
        static {
            System.out.println("静态块");
        }
    }
    

    运行试试,看看会打印出什么,哈哈

    public class Demo {
        public static void main(String[] args) {
           A a = new A();
        }
    }
    
    静态块
    构造快
    构造函数
    

    看出来了吗?

    静态块是跟随着类模板加载的,就像人的眼睛一样,人在哪里,必然眼睛就在哪里,所以第一个是静态块。而构造块是在构造函数运行时除super()方法外首先运行的。

    如果是继承,结果会是什么呢?

    class Parent{
    	static int time = 7;
        Parent(){
            System.out.println("Parent构造函数");
        }
        {
            System.out.println("Parent构造快");
        }
        static {
            System.out.println("Parent静态块");
        }
    }
    class Sun extends Parent{
    	static int time1 = 7;
        Sun(){
            System.out.println("Sun构造函数");
        }
        {
            System.out.println("Sun构造快");
        }
        static {
            System.out.println("Sun静态块");
        }
    }
    
    public class Demo {
        public static void main(String[] args) {
           Sun a = new Sun();
        }
    }
    
    Parent静态块
    Sun静态块
    Parent构造快
    Parent构造函数
    Sun构造快
    Sun构造函数
    

    这是怎么回事呢?为啥和我们想象的不一样啊

    这是因为生活中是先有父亲然后才有儿子,代码中也是一样的,当 new Sun() 的时候实例父亲对象已经存在,结合上面的总结,就可以得出答案。
    执行顺序:

    • 父类静态(不区分方法和字段,直接按照先后顺序)
    • 子类的静态
    • 父类的构造快
    • 父类的构造方法
    • 子类的构造快
    • 子类的构造方法

    现在你懂了吗

    面试也会偶尔会问哦。。。。。

    展开全文
  • 构造方法的定义与使用

    千次阅读 2018-10-26 15:21:04
    构造方法(主要意义是对类中属性初始化) 构造方法的三大特征: a.构造方法名称必须与类名称相同 【1类名称】Persion 【2对象】per1 = 【3】 new 【4 构造方法】Persion(); b.构造方法没有返回值类型声明...

    构造方法(主要意义是对类中属性初始化)

    构造方法的三大特征:

    a.构造方法名称必须与类名称相同

    【1类名称】Persion   【2对象】per1  = 【3】 new  【4 构造方法】Persion();

    b.构造方法没有返回值类型声明(注意不是没有返回值)

    //命名不规范的普通构造
    public void Person(){
        System.out.println("######");
    }
    //无参构造
    public Person(){
        System.out.println("******");
    }

     

    c.每个类中一定要至少存在一个构造方法,如果没有明确定义,系统会自动生成无参构造,若在类中自定义了构造方法,则系统不再默认生成无参构造

        //1个参数的有参构造
        public Person(String n){
            name = n;
        }
        //2个参数的有参构造
        public Person(String n, int num){
            name = n;
            age = num;
        }
        
    
        Person per1 = new Person();

     

     

    构造方法重载:参数个数不同(参数类型已定)

    类定义顺序:

    1.定义属性 -> 2.定义构造方法 ->3.定义普通方法

    class Person{
        private String name;    //定义属性
        private int age = 10;   //定义属性
        //无参构造
        public Person(){        //定义构造方法
            //属性的初始化
            //name = null;
            //age = 10;
        }
        //定义普通方法
        public void getPersonInfo(){
            System.out.println("姓名为:"+name+",年龄为:"+age);
        }
    }
    public class test{
        public static void main(String[] args){
            //根据Person类生产一个对象
            Person per1 = new Person();
            per1.getPersonInfo();
        }
    }
    class Person{
        private String name;
        private int age;
        //无参构造
        public Person(){
            System.out.println("******");
        }
        //有参构造
        public Person(String n, int num){
            name = n;
            setage(num);
        }
        public void setage(int num){
            if(num>0 && num<150){
                age = num;
            }
            else{
                age = 0;
            }
        }
        public int getage(){
            return age;
        }
        public void getPersionInfo(){
            System.out.println("姓名:"+name+", 年龄:"+age);
        }
    }
    public class test{
        public static void main(String[] args){
            Person per1 = new Person("gx",20);
            per1.getPersionInfo();
        }
    }

    展开全文
  • C++11之前,对象的拷贝控制由三个函数决定:拷贝构造函数(Copy Constructor)、拷贝赋值运算符(Copy Assignment operator)和析构函数(Destructor)。 C++11之后,新增加了两个函数:移动构造函数(Move ...

    对象的拷贝控制
    C++11之前,对象的拷贝控制由三个函数决定:拷贝构造函数(Copy Constructor)、拷贝赋值运算符(Copy
    Assignment operator)和析构函数(Destructor)。

    C++11之后,新增加了两个函数:移动构造函数(Move Constructor)和移动赋值运算符(Move Assignment operator)。

    构造函数与赋值运算符的区别
    构造函数在创建或初始化对象的时候调用,而赋值运算符在更新一个对象的值时调用。

    左值与右值的区别
    能出现在赋值号左边的表达式称为“左值”,不能出现在赋值号左边的表达式称为“右值”。一般来说,左值是可以取地址的,右值则不可以。
    非 const 的变量都是左值。函数调用的返回值若不是引用,则该函数调用就是右值。一般的“引用”都是引用变量的,而变量是左值,因此它们都是“左值引用”。

    C++11 新增了一种引用,可以引用右值,因而称为“右值引用”。无名的临时变量不能出现在赋值号左边,因而是右值。右值引用就可以引用无名的临时变量。定义右值引用的格式如下:

    类型 && 引用名 = 右值表达式;
    例如:
    class A{};
    A & rl = A(); //错误,无名临时变量 A() 是右值,因此不能初始化左值引用 r1
    A && r2 = A(); //正确,因 r2 是右值引用
    引入右值引用的主要目的是提高程序运行的效率。有些对象在复制时需要进行深复制,深复制往往非常耗时。合理使用右值引用可以避免没有必要的深复制操作。**

    先来一个简单的例子:

    #include
    using namespace std;

    class A {
    public:
    int x;
    A(int x) : x(x)
    {
    cout << “Constructor” << endl;
    }
    A(A& a) : x(a.x)
    {
    cout << “Copy Constructor” << endl;
    }
    A& operator=(A& a)
    {
    x = a.x;
    cout << “Copy Assignment operator” << endl;
    return *this;
    }
    A(A&& a) : x(a.x)
    {
    cout << “Move Constructor” << endl;
    }
    A& operator=(A&& a)
    {
    x = a.x;
    cout << “Move Assignment operator” << endl;
    return *this;
    }
    };

    A GetA()
    {
    return A(1);
    }

    A&& MoveA()
    {
    return A(1);
    }

    int main()
    {
    A a(1);
    A b = a;
    A c(a);
    b = a;
    A d = A(1);
    A e = std::move(a);
    A f = GetA();
    A&& g = MoveA();
    d = A(1);
    system(“pause”);
    return 0;
    }
    A a(1),调用构造函数。
    A b = a,创建新对象b,使用a初始化b,因此调用拷贝构造函数。
    A c(a),创建新对象c,使用a初始化c,因此调用拷贝构造函数。
    b = a,使用a的值更新对象b,因为不需要创建新对象,所以调用拷贝赋值运算符。
    A d = A(1),创建新对象d,使用临时对象A(1)初始化d,由于临时对象是一个右值,所以调用移动构造函数。
    A e = std::move(a),创建新对象e,使用a的值初始化e,但调用std::move(a)将左值a转化为右值,所以调用移动构造函数。
    A f = GetA(),创建新对象f,使用GetA()函数返回的临时对象初始化f,由于临时对象是右值,所以调用移动构造函数。值得注意的是,这里调用了两次移动构造函数。第一次是GetA()返回前,A(1)移动构造了一个临时对象。第二次是临时对象移动构造f。
    A&& g = MoveA(),没有创建新对象,也不更新任何对象,只是将MoveA()的返回值绑定到右值引用g。因此不调用构造函数,也不调用赋值运算符。
    d = A(1),使用临时对象A(1)更新d,因为不需要创建新对象,所以调用移动赋值运算符。
    再来看一个复杂一点的例子:

    #include
    #include
    #include
    using namespace std;
    class String
    {
    public:
    char* str;
    String() : str(new char[1])
    {
    str[0] = 0;
    }
    // 构造函数
    String(const char* s)
    {
    cout << “调用构造函数” << endl;
    int len = strlen(s) + 1;
    str = new char[len];
    strcpy_s(str, len, s);
    }
    // 复制构造函数
    String(const String & s)
    {
    cout << “调用复制构造函数” << endl;
    int len = strlen(s.str) + 1;
    str = new char[len];
    strcpy_s(str, len, s.str);
    }
    // 复制赋值运算符
    String & operator = (const String & s)
    {
    cout << “调用复制赋值运算符” << endl;
    if (str != s.str)
    {
    delete[] str;
    int len = strlen(s.str) + 1;
    str = new char[len];
    strcpy_s(str, len, s.str);
    }
    return *this;
    }
    // 移动构造函数
    // 和复制构造函数的区别在于,其参数是右值引用
    String(String && s) : str(s.str)
    {
    cout << “调用移动构造函数” << endl;
    s.str = new char[1];
    s.str[0] = 0;
    }
    // 移动赋值运算符
    // 和复制赋值运算符的区别在于,其参数是右值引用
    String & operator = (String && s)
    {
    cout << “调用移动赋值运算符” << endl;
    if (str != s.str)
    {
    // 在移动赋值运算符函数中没有执行深复制操作,
    // 而是直接将对象的 str 指向了参数 s 的成员变量 str 指向的地方,
    // 然后修改 s.str 让它指向别处,以免 s.str 原来指向的空间被释放两次。
    str = s.str;
    s.str = new char[1];
    s.str[0] = 0;
    }
    return *this;
    }
    // 析构函数
    ~String()
    {
    delete[] str;
    }
    };
    template
    void MoveSwap(T & a, T & b)
    {
    T tmp = move(a); //std::move(a) 为右值,这里会调用移动构造函数
    a = move(b); //move(b) 为右值,因此这里会调用移动赋值运算符
    b = move(tmp); //move(tmp) 为右值,因此这里会调用移动赋值运算符
    }
    template
    void Swap(T & a, T & b)
    {
    T tmp = a; //调用复制构造函数
    a = b; //调用复制赋值运算符
    b = tmp; //调用复制赋值运算符
    }
    int main()
    {
    String s;
    // 如果没有定义移动赋值运算符,则会导致复制赋值运算符被调用,引发深复制操作。
    s = String(“this”); //调用移动赋值运算符
    cout << s.str << endl;
    String s1 = “hello”, s2 = “world”;
    //MoveSwap(s1, s2); //调用一次移动构造函数和两次移动赋值运算符
    Swap(s1, s2);
    cout << s2.str << endl;
    system(“pause”);
    return 0;
    }

    移动赋值运算符和复制赋值运算符的区别在于,其参数是右值引用。在移动赋值运算符函数中没有执行深复制操作,而是直接将对象的 str 指向了参数 s 的成员变量 str 指向的地方,然后修改 s.str 让它指向别处,以免 s.str 原来指向的空间被释放两次。

    该移动赋值运算符函数修改了参数,这会不会带来麻烦呢?答案是不会。因为移动赋值运算符函数的形参是一个右值引用,则调用该函数时,实参一定是右值。右值一般是无名临时变量,而无名临时变量在使用它的语句结束后就不再有用,因此其值即使被修改也没有关系。

    s = String(“this”),如果没有定义移动赋值运算符,则会导致复制赋值运算符被调用,引发深复制操作。临时无名变量String(“this”)是右值,因此在定义了移动赋值运算符的情况下,会导致移动赋值运算符被调用。移动赋值运算符使得 s 的内容和 String(“this”) 一致,然而却不用执行深复制操作,因而效率比复制赋值运算符高。

    虽然移动赋值运算符修改了临时变量 String(“this”),但该变量在后面已无用处,因此这样的修改不会导致错误。

    MoveSwap函数
    T tmp = move(a),使用了 C++ 11 中的标准模板 move。move 能接受一个左值作为参数,返回该左值的右值引用。因此本行会用以右值引用作为参数的移动构造函数来初始化 tmp。该移动构造函数没有执行深复制,将 tmp 的内容变成和 a 相同,然后修改 a。由于调用 MoveSwap 本来就会修改 a,所以 a 的值在此处被修改不会产生问题。

    a = move(b)和b = move(tmp)调用了移动赋值运算符,在没有进行深复制的情况下完成了 a 和 b 内容的互换。

    Swap 函数
    Swap 函数执行期间会调用一次复制构造函数,两次复制赋值运算符,即一共会进行三次深复制操作。而利用右值引用,使用 MoveSwap,则可以在无须进行深复制的情况下达到相同的目的,从而提高了程序的运行效率。

    Move 语义
    std::move 是获得右值的方式,通过 move 可以将左值转为右值。

    在 C++11,一个 std::vector 的 “move 构造函数” 对某个 vector 的右值引用,可以单纯地从右值复制其内部 C-style 数组的指针到新的 vector,然后留下空的右值。
    #include
    using namespace std;

    int main()
    {
    unique_ptr pa(new string(“CHN”));
    //unique_ptr没有use_count()方法
    unique_ptr pb(new string(“USA”));
    // std::move 是获得右值的方式
    // 通过move可以将把左值转换为右值,同时清空右值
    pb = move(pa);
    //pb=pa;//错误,不能直接用等于号
    if (pa == nullptr)
    {
    cout << “pa现在为空” << endl;
    }
    system(“pause”);
    return 0;
    }

    展开全文
  • c++ 构造函数详解

    万次阅读 多人点赞 2019-05-31 17:20:58
    c++构造函数详解。(构造函数的分类、拷贝构造函数)
  • Java中类的构造方法

    万次阅读 多人点赞 2016-10-20 23:17:50
    构造函数。在创建对象的时候,对象成员可以由构造函数方法进行初始化。new对象时,都是用构造方法进行实例化的; 例如;Test test = new Test("a"); //Test("a");其中这个就是构造函数,“a”为构造方法的...
  • 构造函数与初始化列表

    千次阅读 多人点赞 2018-08-01 18:17:33
    0.初始化与赋值的区别 意义上: 1)初始化:一个变量或者一个对象在产生的时候就赋予一个值,属于伴随性质 2)赋值:在一个变量或者一个对象在产生之后的任意时刻赋予一个值,属于任意性质 ...
  • 构造入门

    2019-07-26 11:22:00
    构造死磕 什么是构造 小学中学奥数 先用数学解决再编程实现的构造题 一般算法无法解决 \(NOI+\)难度\(PJ-\)代码量 坑 构造举例 CF743C Vladik and fractions 题目让我们构造一组数字,满足\(\frac{2}{n} = \frac{1...
  • 构造代码块 和 构造方法 执行顺序

    千次阅读 2019-01-03 11:42:57
    构造代码块:定义在类的成员位置,直接使用{ },在{}中写代码内容。 位置:类中,方法外,和方法并列,和先后位置无关。 执行时机:创建对象的时候执行一次。在构造方法隐式3步的最后一步。当构造代码块执行结束...
  • 构造过程

    2019-07-08 15:42:46
    只写类型,在构造器中赋初始值 当前是缺省值,以后一定有值。或者当前是缺省值,以后可能还是缺省值。 class Test { //给属性赋默认值 var a = 0 //给属性类型,默认值在构造器中赋值 var b: Int //当前是...
  • 二叉排序树(BST)构造与应用

    万次阅读 2016-03-20 23:23:46
    二叉排序树(BST)构造与应用     二叉排序树(BST):又称二叉查找树,其定义为:二叉排序树或者是空树,或者是满足以下性质的二叉树。  (1) 若它的左子树非空,则左子树上所有记录的关键字均小于根记录的值。  (2)...
  • 数据结构之二叉排序树的建立

    万次阅读 多人点赞 2018-06-12 18:57:15
    一、普通二叉树的建立 提到二叉树的建立,就不得不提一下“递归”,建立二叉树所采用的思想就是递归。递归基本形式: void recursion() { if(递归结束条件) { 表达式 } else { 表达式;...
  • 简单总结就是:构造函数不可以是虚函数,而析构函数可以且常常是虚函数。 构造函数不能是虚函数 1. 从vptr角度解释 虚函数的调用是通过虚函数表来查找的,而虚函数表由类的实例化对象的vptr指针(vptr可以参考C++...
  • 哈夫曼树原理,及构造方法

    万次阅读 多人点赞 2018-08-05 12:13:21
    哈夫曼树(最优二叉树) 百度百科:... 一.... 找出存放一串字符所需的最少的二进制编码 二. 构造方法: 首先统计出每种字符出现的频率!(也可以是概率)//权值 ----------------------------...
  • C++拷贝构造函数详解

    万次阅读 多人点赞 2011-02-23 13:39:00
    什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。 下面看一个类对象...
  • [Java基础]-- 有参构造方法和无参构造方法

    万次阅读 多人点赞 2016-03-03 15:06:44
    java构造方法:有参构造方法和无参构造方法   一、无参构造方法 1、定义: 如果编写一个javaBean时没有添加无参构造方法,那么编译器会自动添加无参构造方法; 但是如果编写时添加了有参构造方法而未添加无参...
  • 二进制LDPC码的构造及译码算法

    千次阅读 2018-09-09 16:11:04
    构造好的LDPC码校验矩阵和设计性能优异的译码算法是LDPC码研究领域的重点。  常见的LDPC码一般分为两类,一类是随机LDPC码,一般由随机化方法构造;另一类是准循环LDPC码,一般由半随机方 法或者基于代数的结构化...
  • 请移步链接:https://www.javaclub.club/blog/article.html?id=14
  • 构造函数

    千次阅读 2016-03-07 22:28:52
    构造函数  类通过一个或几个特殊的成员函数控制类对象初始化过程这样的成员函数为构造函数。构造函数的函数名与类名相同,没有返回类型,不能声明为const成员函数(因为直到构造函数初始化过程后,对象才能真正的...
  • JAVA构造函数(方法)

    千次阅读 多人点赞 2018-12-27 14:47:11
    一、什么是构造函数 java构造函数,也叫构造方法,是java中一种特殊的函数。函数名与类名相同,无返回值。 作用:一般用来初始化成员属性和成员方法的,即new对象产生后,就调用了对象了属性和方法。 构造函数是...

空空如也

1 2 3 4 5 ... 20
收藏数 2,660,132
精华内容 1,064,052
关键字:

构造