【C++】类和对象(生存周期及初始化列表、常对象常方法)

生存周期:

1. 对于全局对象,程序一开始,其构造函数就先被执行(比程序进入点更早);程序即将结束前其析构函数将被执行。

2. 对于局部对象,当对象诞生时,其构造函数被执行;当程序流程将离开该对象的声明周期时,其析构函数被执行。

3. 对于静态(static)对象,当对象诞生时其构造函数被执行;当程序将结束时其析构函数才被执行,但比全局对象的析构函数早一步执行。

4. 对于以new方式产生出来的局部对象,当对象诞生时其构造函数被执行,析构函数则在对象被delete时执行时执行

类类型的返回值:

        无论多少字节,都是由临时对象带出来。

临时对象的生存周期:遇到表达式结束(在表达式之后)

#include <iostream>
using namespace std;
 
class Test
{
public:
    Test(int a=5, int b=5):ma(a), mb(b)
    {
		cout<<"Test(int, int)"<<endl;
	}
    ~Test()
    {
		cout<<"~Test()"<<endl;
	}
    Test(const Test &src):ma(src.ma), mb(src.mb)
    {
		cout<<"Test(const Test&)"<<endl;
	}
    void operator=(const Test &src)
    {
		ma = src.ma; 
		mb = src.mb; 
		cout<<"operator="<<endl;
	}
private:
    int ma;
    int mb;
};
Test t1(10, 10);//程序运行时开辟,程序结束时销毁
 
int main()
{
    Test t2(20, 20);//调用带两个参数的构造函数(从调用点到main函数结束)
    Test t3=t2;//调用拷贝构造函数
    t2 = t3;//调用赋值运算符重载函数
    static Test t4 = Test(30, 30);//调用拷贝构造函数
    t2 = Test(40, 40);//调用构造函数构造临时对象 赋值运算符的重载函数 析构函数
    t2 = (Test)(50, 50);//强转相当于逗号表达式 :等价于t2=(Test)50;调用调用构造函数构造临时对象 调用赋值运算符的重载函数 析构函数
    t2 = 60;//隐式生成临时对象 构造函数 赋值运算符的重载函数 析构函数
    Test *p1 = new Test(70, 70);//产生内存 调用构造函数(在堆上开辟内存,需要手动释放,调用delete(否则会产生内存泄漏))
    Test *p2 = new Test[2];//产生内存 构造函数 
    Test *p3 = &Test(80, 80);//构造函数 析构函数(显式生成临时对象)
    Test &p4 = Test(90, 90);//构造函数
    //引用提升临时对象的生存周期,不会销毁,因为临时对象的生存周期没有到
    delete p1;//析构函数
    delete []p2;//析构函数
}
Test t5(100, 100);//构造函数

初始化列表:

          构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。

struct和类的区别:

         struct是公有的;

        类只有在public中为公有,其余为private。

构造函数的初始化列表的执行顺序和成员变量的声明有关。

class CExample {
public:
    int a;
    float b;
    //构造函数初始化列表
    CExample(): a(0),b(8.8)
    {}
    //构造函数内部赋值
    CExample()
    {
        a=0;
        b=8.8;
    }
};

成员对象:const 、引用、static、explicit、mutable

explicit:禁止隐式生成对象

mutable:去除常性。

class example
{
public :
	explicit Test(int a,int b = 0):ma(a),mb(b)//禁止隐式生成对象
	void ChangeSecondMember()const 
	{
		mb = 20;
	}
	this->mb = 20;
private:
	int ma;
	mutable int mb;//去除常性后,mb可修改
};

成员方法的调用

普通的成员方法的调用(依赖对象的调用)

静态的成员方法不能调用普通的成员方法

        常对象只能调动常方法 ,不能调用普通的成员方法。
        普通对象还可以调用常方法
        常方法中不能调动普通的成员方法
        普通的成员方法中可以调用常方法

常对象:

          常对象必须在定义对象时就指定对象为常对象。

          常对象中的数据成员为常变量且必须要有初始值,如

const Test test1(10,20)

          凡希望保证数据成员不被改变的对象,可以声明为常对象。 

常对象只能调动常方法

#include<iostream>
using namespace std;
 
class Test
{
public:
	Test(int a, int b):mb(b)
	{
		ma = a;
		//mb = b;
	}
	void Show()const//此时是一个常方法
	{
		cout << "ma:" << ma << endl;
		cout << "mb:" << mb << endl;
	}
private:
	
	int ma;
	const int mb;
};
 
int main()
{
	const Test test1(10,20);//常对象
	test1.Show();
	return 0;
}

void Show()const   加const  此时Show是一个常方法

常方法:this类型: const Test* const

相当于  const Test* const this=&test1;

此时 *this被const修饰,没有被间接修改的风险,编译器允许通过。
 

 不能调用普通的成员方法。

void Show()const//常方法
{
	cout << "ma:" << ma << endl;
	cout << "mb:" << mb << endl;
        /**错误**/
	//Show(ma);
	//this->Show(ma); //  常方法this指针类型 const Test* const
	(*this).Show(ma);//左边是常对象,常对象不能调用普通方法
}
 
void Show(int a)
{
	cout << "ma:" << ma << endl;
	cout << "mb:" << mb << endl;
}

常方法里面的this指针指向的是常对象,常对象不能调用普通方法。

普通对象可以调用常方法

 int main()
    {
        Test test2(10,20);
        test2.Show();//普通对象可以调用常方法
        return 0;
    }

Test test2(10,20);//普通对象
test2.Show();
这里相当于:const Test* const this=&test2;

普通方法可以调用常方法

 void Show()const//常方法
    {
        cout << "ma:" << ma << endl;
        cout << "mb:" << mb << endl;
    }
     
    void Show(int a)//普通成员方法
    {
        cout << "ma:" << ma << endl;
        cout << "mb:" << mb << endl;
        (*this).Show();
    }

总结:

          常函数,可以理解为将this换了一种修饰方式:this指针只能一直指向当前对象,相当于 Test * const this;,常函数就可以理解为cosnt Test * const this;

#include<iostream>
using namespace std;
 
class Test
{
public:
	void change()
	{
		m_a = 99;
		cout << "change函数" << endl;
	}
 
	void showinfo()  const  //使用const修饰,使得这个函数变为常函数
	{
		//m_a = 99;  //常函数不可以修改
		m_b = 99;  //常函数可以修改mutable修饰的成员变量
		cout << "常函数" << endl;
	}
	
private:
	int m_a;
	mutable int m_b;  //就算是常函数也可以进行修改
};
 
 
int main()
{
	Test p1;
	const Test p2; //常对象
	p1.change();
	//p2.change(); //常对象不可以调用普通函数
	p2.showinfo();// 常对象可以调用常函数
	return 0;
}
  1.  

  

猜你喜欢

转载自blog.csdn.net/like_that/article/details/89054971
今日推荐