[类和对象]构造和析构

有关构造函数 

1构造函数定义及调用

  1)C++中的类可以定义与类名相同的特殊成员函数,这种与类名相同的成员函数叫做构造函数;

  2)构造函数在定义时可以有参数;

  3)没有任何返回类型的声明。

2构造函数的调用

  自动调用:一般情况下C++编译器会自动调用构造函数

  手动调用:在一些情况下则需要手工调用构造函数

有关析构函数 

析构函数定义及调用

  1)C++中的类可以定义一个特殊的成员函数清理对象,这个特殊的成员函数叫做析构函数

    语法:~ClassName()

  2)析构函数没有参数也没有任何返回类型的声明  

  3)析构函数在对象销毁时自动被调用

  4)析构函数调用机制

    C++编译器自动调用     

          先创建的对象 后释放

Q对象销毁是发生在什么时候?

A对象的析构函数在的对象销毁前被调用,对象何时销毁也与其作用域有关。

例如,全局对象是在程序运行结束时销毁,自动对象是在离开其搜索作用域时销毁,而动态对象则是在使用delete运算符时销毁。


#include <iostream>
using namespace std;

class Test2
{
public:
//无参数构造函数
    Test2()
    {
        m_a = 0;
        m_b = 0;
        cout<<"无参数构造函数"<<endl;
    }

//有参数构造函数
    Test2(int a)
    {
        m_a = a;
        m_b = 0;
    }

    Test2(int a, int b)
    {
        m_a = a;
        m_b = b;
        cout<<"有参数构造函数"<<endl;
    }

//赋值构造函数 (copy构造函数)
    Test2(const Test2& obj)
    {
        cout<<"我也是构造函数 " <<endl;
    }

public:
    void printT()
    {
        cout<<"普通成员函数"<<endl;
    }

private:
    int m_a;
    int m_b;
};

int main01()
{
    Test2 t1;  //调用无参数构造函数
    cout<<"hello..."<<endl;

    return 0;
}

//调用 调用有参数构造函数 3
int main(void)
{
    //1括号法
    Test2 t1(1, 2);  //调用参数构造函数  c++编译器自动的调用构造函数
    t1.printT();

    // 2 =号法[但这是一个很鸡肋的用法]
    Test2 t2 = (3, 4); // = c++对等号符 功能增强  c++编译器自动的调用构造函数

    //对象的初始化 和 对象的赋值 是两个不同的概念
    //3 对象的初始化
    Test2 t4 = Test2(1, 2);  //匿名对象
    t1 =  t4;  //把t4 copy给 t1  //赋值操作 

    //4 赋值构造函数 (copy构造函数)
    Test2 t5 = Test2(t1); //等价于Test2 t5(t1);  等价于 Test2 t5 = t1;


    //☆ Test2 t5 = Test2(t1);是程序员手工的调用构造函数 


    cout<<"hello..."<<endl;

    return 0;
}

/*==============================================  END File ==============================================*/

有参数构造函数
普通成员函数
有参数构造函数
我也是构造函数
hello...



赋值构造函数的4种应用场景

这是初始化的两种; Test t2 = t1; Test t2(t1);

第三种是功能函数的形参是一个元素的时候{非指针,非引用},这个时候实参给形参的时候必然调用拷贝构造

第四种是你说的返回,返回一个对象的时候,但这个时候返回的是匿名对象,

  如果是初始化,是直接会转换为要初始化的那个对象的,
  如果是赋值操作,这个时候确实会调用copy构造,但是这个对象的生命周期只有那么一行,用完立即被析构

#include <iostream>

using namespace std;

class Test4
{
public:
    Test4()  //无参数构造函数
    {
        m_a = 0;
        m_b = 0;
        cout<<"无参数构造函数"<<endl;
    }

    Test4(int a)
    {
        m_a = a;
        m_b = 0;
    }

    Test4(int a, int b) //有参数构造函数
    {
        m_a = a;
        m_b = b;
        cout<<"有参数构造函数"<<endl;
    }

    Test4(const Test4& obj )//赋值构造函数 (copy构造函数)
    {
        cout<<"赋值构造函数 " <<endl;
        m_b = obj.m_b + 100;
        m_a = obj.m_a + 100;
    }                                                                

public:
    void printT()
    {
        cout<<"普通成员函数"<<endl;
        cout<<"m_a"<<m_a<<" m_b"<<m_b<<endl;
    }
private:
    int m_a;
    int m_b;
};

//1  赋值构造函数 用1个对象去初始化另外一个对象
int main(void)
{
    Test4 t0(1, 2);
    Test4 t1(1, 2);

    /*赋值操作 和 初始化是两个不同的概念
        =的赋值操作   不会调用构造函数
        =的初始化操作   会调用构造函数 */ 
    //operator=()//抛砖
    t0 = t1; //用t1 给 t0赋值  

    //第1种调用方法
    Test4 t2 = t1; //用t1来初始化 t2     【one】
    t2.printT();

    //第2种调用方法
    Test4 t3(t1);  //用t1对象 初始化 t2对象   【two】
    t2.printT();

    cout<<"hello..."<<endl;

    return 0;
}

[Three]

#include <iostream>
using namespace std;

class Location
{
public:
    Location( int xx = 0 , int yy = 0 )
    {
        X = xx ;  Y = yy ;  cout << "None Param Constructor Func.\n" ;
    }

    //copy构造函数  完成对象的初始化
    Location(const Location & obj) //copy构造函数
    {
        cout << "Copy Constructor func.\n" ;
        X = obj.X;
        Y = obj.Y;
    }

    ~Location()
    {
        cout << X << "," << Y << " Object destroyed." << endl ;
    }

    int  GetX () {
        return X ;
    }

    int GetY () {
        return Y ;
    }
private:
    int  X , Y ;
};

//业务函数  形参是一个元素
void f(Location p)
{
    cout<<"业务函数"<<endl;
    cout<<p.GetX()<<endl;
}

void playobj()
{
    Location  a(1, 2);
    Location  b = a;
    cout<<"b对象已经初始化完毕"<<endl;

    f(b); //实参b传给形参p会调用copy构造函数
}

int main()
{
    playobj();
    cout<<"hello..."<<endl;
    return 0;
}

None Param Constructor Func.
Copy Constructor func.
b对象已经初始化完毕
Copy Constructor func.
业务函数
1
1,2 Object destroyed.
1,2 Object destroyed.
1,2 Object destroyed.
hello...

[Four]

#include <iostream>
#include <cstdio>

using namespace std;

class Location
{
public:
    Location( int xx = 0 , int yy = 0 )
    {
        X = xx ;  Y = yy ;  cout << "Constructor Object.\n" ;
    }

    //copy构造函数  完成对象的初始化
    Location(const Location & obj) //copy构造函数
    {
        X = obj.X; Y = obj.Y;
    }

    ~Location()
    {
        cout << X << "," << Y << " Object destroyed." << endl ;
    }

    int  GetX () { return X ; }        

    int  GetY () { return Y ; }
private :   int  X , Y ;
} ;

/*******************************************************************************************************************
    g函数 返回一个元素
    结论1 : 函数的返回值是一个元素 (复杂类型的), 返回的是一个新的匿名对象(所以会调用匿名对象类的copy构造函数)

    结论2: 有关 匿名对象的去和留
    如果用匿名对象  初始化 另外一个同类型的对象, 匿名对象 转成有名对象
    如果用匿名对象  赋值给 另外一个同类型的对象, 匿名对象 被析构

    你这么写代码,设计编译器的大牛们:
    我就给你返回一个新对象(没有名字 匿名对象)
*******************************************************************************************************************/
Location g()
{
    Location A(1, 2);
    return A;
}

//
void objplay2()
{
    g();
}

//
void objplay3()
{
    //用匿名对象初始化m 此时c++编译器 直接把匿名对转成m;(扶正) 从匿名转成有名字了m
    Location m = g();
    printf("\r\n匿名对象,被扶正,不会析构掉\n");
    cout<<m.GetX()<<endl;
}

void objplay4()
{
    //用匿名对象 赋值给 m2后, 匿名对象被析构
    Location m2(1, 2);
    m2 = g();
    printf("\r\n因为用匿名对象=给m2, 匿名对象,被析构\n");
    cout<<m2.GetX()<<endl;;
}
int main(void)
{
    objplay2();
//    objplay3();
//    objplay4();
    cout<<"hello..."<<endl;

    return 0;
}

二个特殊的构造函数

1) 默认无参构造函数

    当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空

2) 默认拷贝构造函数

    当类中没有定义拷贝构造函数时,编译器默认提供一个默认拷贝构造函数,简单的进行成员变量的值复制

1)当类中没有定义任何一个构造函数时, c++编译器会提供默认无参构造函数和默认拷贝构造函数
2)当类中定义了拷贝构造函数时, c++编译器不会提供无参数构造函数
3)当类中定义了任意的非拷贝构造函数(即:当类中提供了有参构造函数或无参构造函数), c++编译器不会提供默认无参构造函数
4 )默认拷贝构造函数成员变量简单赋值
总结:只要你写了构造函数,那么你必须用。

构造析构阶段性总结
1)构造函数是C++中用于初始化对象状态的特殊函数
2)构造函数在对象创建时自动被调用, 在对象离开其作用域时候自动销毁
3)构造函数和普通成员函数都遵循重载规则
4)拷贝构造函数是对象正确初始化的重要保证
5) 必要的时候,必须手工编写拷贝构造函数

时间: 2024-10-13 21:47:34

[类和对象]构造和析构的相关文章

C++ 类成员的构造和析构顺序

我想对面向对象有了解的童鞋应该不会对类和对象感到陌生吧 ! 对象并不是突然建立起来的,创建对象必须时必须同时创建父类以及包含于其中的对象.C++遵循如下的创建顺序: (1)如果某个类具体基类,执行基类的默认构造函数. (2)类的非静态数据成员,按照声明的顺序创建. (3)执行该类的构造函数. 即构造类时,会先构造其父类,然后创建类成员,最后调用本身的构造函数. 下面看一个例子吧 class c { public: c(){ printf("c\n"); } protected: pri

python-装饰器,类与对象,私有字段,析构,__call__,继承,多继承,接口

1.装饰器执行流程 装饰器:将原函数替换为wrapper函数 def outer() @outer  --- func1作为参数传入outer() def wrapper()  --- wrapper()放入内存 return wrapper   --- 返回wrapper地址,Func1重新赋值为wrapper Func1()  --- 调用func1函数 def wrapper() print '验证' def Func1() print 'func1' [[email protected]

完整类实现:构造,析构,遍历二叉树

根据前面一个博文内容已经讲述了如何根据两种遍历方式进行构建二叉树 这里利用递归方式遍历二叉树,递归方式比较简单,后续补充其余非递归方式 再此主要是完善类的使用: 其中重点在于:接口定义 二叉树的析构删除 以及类成员变量中如果有指针,同时涉及复制构造函数和赋值操作符函数时需要用到的智能指针 如果接口方面定义不够好,还望包涵 如果有对智能指针不理解的地方,可以移步 http://blog.csdn.net/xietingcandice/article/details/39670269 .h文件 #i

关于类继承的构造与析构调用分析

总体结论:派生类的构造函数在创建对象时调用,调用顺序如下: 1.调用虚基类的构造函数(若有多个虚基类,调用顺序为继承的顺序.): 2.调用基类的构造函数(若有多个基类,调用顺序为继承的顺序.): 3.调用类类型的成员对象的构造函数(调用顺序为定义的顺序): 4.调用自身的构造函数. 析构函数的调用顺序一般和构造函数的调用顺序相反,但分如下几种情况: 1.当父类的指针 new一个子类的临时对象时.若父类的析构不是虚函数,则delete的时候不调用子类的析构,只调用父类的析构:    若父类的析构是

C++ 派生类对象的构造与析构过程

C++ 派生类对象的构造与析构过程 因为基类的成员变量和派生类的成员变量在内存中的连续的(下面程序会验证这一点),如下图所示: 所以构造派生类对象的时候,构造成员变量的过程就像入栈一样: 那么很自然,派生类对象析构的时候就是出栈的过程,先进后出,后进先出: 下边一个简单的程序验证这个结论: #include <iostream> using namespace std; class base{ int a; public: base(const int& a):a(a){cout<

PHP面向对象基本概念 类与对象 静态属性 构造/析构方法

1.传统的面向过程和现代面向对象  传统面向过程:是指把将要完成的工作分为若干个步骤一步一步的完成  现代面向对象:是指将要完成的工作拆分为一个一个的对象的任务(功能)每个对象独自完成自己的任务 可以理解为: 一个大扫除 面向过程就是一个人干完大扫除 面向对象就是 一个人扫地 一个人拖地2.面向对象的基本概念  三大特性:封装 继承 多态  类与对象:          张三是一个对象,李四是一个对象 他们都隶属于人这个类         类:描述某一些具有共同特征的物体的概念        

C++ 类的继承三(继承中的构造与析构)

//继承中的构造与析构 #include<iostream> using namespace std; /* 继承中的构造析构调用原则 1.子类对象在创建时会首先调用父类的构造函数 2.父类构造函数执行结束后,执行子类的构造函数 3.当父类的构造函数有参数时,需要在子类的初始化列表中显示调用 4.析构函数调用的先后顺序与构造函数相反 继承与其他类做成员变量混搭的情况下,构造和析构嗲用原则 1.先构造父类,在构造成员变量,最后构造自己 2.先析构自己,再析构成员变量,最后析构父类 */ clas

【C/C++学院】0819-/类的成员函数与const-mutable /构造与析构/拷贝构造deletedefault以及深浅拷贝/静态成员函数成员变量类在内存的存储默认参数/友元类以及友元函数

类的成员函数与const-mutable 成员函数 Fushu.h #pragma once #include <iostream> class fushu { public: int x; int y; public: fushu(); ~fushu(); void show(); inline void showall(int x, int y);//显式内联 void setxy(int x, int y);//编译器优化,默认隐式内联 void show(int x, int y);

Php面向对象学习笔记 – 构造、析构、对象赋值、克隆

Php面向对象学习笔记 – 构造.析构.对象赋值.克隆 class student { public  $stu_id;       // 定义成员变量 public  $stu_name; public  function sayName()   // 成员函数 { echo $this->stu_name;   // $this  访问该对象的成员变量 } } $stu = new  Student;      // 创建对象 $stu->stu_id = '0607001'; $stu-