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++进阶剖析