C++进阶剖析( 十 一)之临时对象和const对象

1.1 临时对象的引出
1.1.1思考程序输出

//下面程序的期望是 Test()中复用Test(int i)函数。但是实际结果不是自己想象的那样。因为构造函数的调用和普通函数是不同的。

class Test
{
private:
	int i ;
public:
	Test()
	{
		Test(0);  // 构造函数中调用构造函数
		printf("Test()\n");
	}
	Test(int i)
	{
		this->i =i;
		printf("Test(int i)\n");
	}
	void print()
	{
		printf("i =%d\n",i);
	}
	~Test()
	{
		printf("~Test() function  i =%d\n",i);
	}
};
int main()
{
	Test  t1;
	t1.print();
	return 0;
}
  • 程序意图
    (1)在Test() 中以0 作为参数调用Test(int i);
    (2)将成员变量mi的初始值设置为0
  • 运行结果
    在这里插入图片描述

1.1.2 案例二

class Test
{
private:
	int i ;
public:

	Test(int i)
	{
		this->i =i;

	}
	void print()
	{
		printf("i =%d\n",i);
	}

};
int main()
{
	Test(10).print();
	int(10) ;	//通过类比,可以得出的内容
	printf("int(10) = %d\n",int(10));
	return 0;
}

结果:
在这里插入图片描述
1.1.3 构造函数分析
构造函数是一个特殊的函数

  • 是否可以直接调用?
  • 是否可以在构造函数中调用构造函数?
  • 直接调用构造函数的行为是什么 ?

直接调用构造函数的结果是什么

答案:

  • 直接调用构造函数将产生一个临时对象
  • 临时对象的生命周期只有一条语句的时间
  • 临时对象的作用域只在一条语句中
  • 临时对象是C++中值得警惕的灰色地带

1.1.4 解决方案

  • 构建一个普通的初始化函数,然后构造函数调用这个初始化函数。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
class Test
{
private:
	int i ;
	void  init(int i)
	{
		this->i =i;
	}
public:
	Test()
	{
		init(0);
	}
	Test(int i)
	{
		init(i);
	}
	void print()
	{
	printf("i =%d\n",i);
	}
};
 int main()
 {
	Test  t1;
	t1.print();
	 return 0;
 }
   

1.2
1.2.1

  • 现代C++编译器在不影响最终执行结果的情况下,会尽力减少临时对象的产生。
  • 之前课程中介绍的copy构造函数第四种调用时机和临时对象之间的关系。
    注意下面两种情况下,哪种会调用copy 构造函数。
    Test func()
    {
    return Test(10); //不会调用Copy构造
    }
    Test func()
    {
    Test t(10);
    return t; // 会调用copy构造函数。
    }

1.3const 对象

1.3.1 问题提出
const 可以修饰普通类型的数据比如const int a =10;
类也是一种类型,那么可以用const修饰类类型的变量吗?(类类型的变量也就是类的对象)
const修饰的变量有什么特性呢?

1.3.2 const 对象

  • const 关键字能够修饰对象
  • const 修饰的对象是只读对象(不能出现在赋值符合的左边)
  • 只读对象的成员变量不允许被改变
  • 只读对象是编译阶段的概念,运行时无效

1.3.3 C++中的const 成员函数

  • const对象只能调用const 的成员函数

  • const成员函数只能调用const成员函数

  • const成员函数不能直接改写成员变量的值

  • const成员函数的语法规则:
    (1) int ClassName::functionName(int a) const
    (2) const 在这了修饰的是this指针。等价于
    int ClassName::functionName(const ClassName * const this,int a)

    注意: this 指针本来就是常量指针

    注意:类中的函数声明和实际函数定义中都必须带const 关键字。

1.4 经典问题
1.4.1 成员函数和成员变量都是隶属于具体对象的吗?

  • 从面向对象的角度
    • 对象由属性(成员变量)和方法(成员函数)构成
  • 从程序运行的角度
    • 对象由数据和函数构成
      • 数据可以位于栈,堆和全局数据区
      • 函数只能位于代码段

1.4.2 结论

  • 每一个对象拥有自己独立的属性(成员变量)
  • 所有的对象共享类的方法
  • 方法能够直接访问对象的属性
  • 方法中的隐藏参数 this 用于指代当前对象
  • 成员函数只有一套,成员函数可以直接访问对应类的任意对象的成员变量

1.4.3

class Test
{
private:
	int mi;
public:
	Test(int i)
	{
		mi =i;
	}
	Test(const Test&j)
	{
		mi =j.mi; //why sucess  成员函数只有一套,成员函数可以直接访问对应类的任意对象的成员变量
		// mi = j.getMi(); //why error  const 对象只能调用const成员函数
		printf("Test(const Test&j)\n");
	}
	int getMi()   // need   int getMi() const 
	{
		return mi ;
	}
	void print()
	{
		printf("Test %p\n",this);
	}
};
int main()
{
	Test t1(1);
	printf("Test t1 =%p\n",&t1);
	t1.print();

	Test t2(2);
	printf("Test t2 =%p\n",&t2);
	t2.print();
	
	Test t3 = t1;
	return 0;
}

在这里插入图片描述

参考一 :狄泰软件学院C++进阶剖析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值