如何调用成员函数
调用类的成员函数的有趣方法。你必须在需要调用的成员函数前面附上类的实例名(或称类的变量,也就是对象)。
Fruit melon, orange, banana;
int main() {
melon.slice();
orange.juice();
return 0;
}
只有这样做,这些成员函数才能被调用,并执行各自的任务。这有点像预定义的操作符。调用一个类对象的成员函数相当于面向对象编程语言所使用的“向对象发送一条信息”这个术语。
每个成员函数都有一个this指针参数,它是隐式赋给函数的,它允许对象在成员函数内部引用对象本身。注意,在成员函数内部,你应该发现this指针并未显式出现,这也是语言本身所设计的。
class Fruit {
public: void peel();
private: int weight, colories_per_oz;
};
void Fruit::peel() {
printf("this ptr = %p", this);
this->weight--;
weight--;
}
Fruit apple;
printf("address of apple = %x", &apple);
apple.peel();
/*
**编程挑战
*/
/*
*调用成员函数
*1.调用在前面的例子中所编写的slice()和juice()成员函数。
*2.试验一下this指针是否是隐式传递给每个成员函数的第一个参数。
*/
#include <stdio.h>
#include <stdlib.h>
class Fruit {
public: void peel();
private: int weight, colories_per_oz;
};
void Fruit::peel() {
printf("this ptr = %p\n", this);
this->weight--;
weight--;
}
int main( void ){
Fruit apple;
printf("address of apple = %p\n", &apple);
apple.peel();
return EXIT_SUCCESS;
}
输出:
构造函数和析构函数
绝大多数类至少具有一个构造函数。当创建类的一个对象时,会隐式地调用构造函数,它负责对象的初始化。与之相对应,类也存在一个清理函数,称为析构函数。当对象被销毁(超出生存期范围或进行delete操作,回收它所使用的堆内存)时,会自动调用析构函数。析构函数不如构造函数常用,它里面的代码一般用于处理一些特殊的终止要求以及垃圾收集等。有些人把析构函数当做一种保险方法来确保对象离开适当的范围时,同步锁总能够被释放。所以它们不仅清除对象,还清理对象所持有的锁。构造函数和析构函数是非常需要的,因为类外的任何函数都不能访问类的private数据成员。因此,你需要类内部有一个特权函数来创建一个对象并对其进行初始化。
相对于C语言,这是一个小小的飞跃。在C语言中,只能使用赋值符号在变量定义时对它进行初始化,或干脆使它保持未初始化状态。可以在C++的类中声明多个构造函数,并通过参数来区分它们。构造函数的名字总是和类的名字一样:
Classname::Classname(arguments) {
...
}
以Fruit类为例:
class Fruit {
public: peel(); slice();juice();
Fruit(int i, int j); //构造函数
~Fruit(); //析构函数
private: int weight, calories_per_oz;
};
//构造函数体
Fruit::Fruit(int i, int j) {
weight = i; calories_per_oz = j;
}
//对象声明时由构造函数进行初始化
Fruit melon(4, 5), banana(12, 8);
构造函数是必要的,因为类通常包含一些结构,而结构又可能包含许多字段。这就需要复杂的初始化。当创建类的一个对象时,会自动调用构造函数,程序员永远不应该显式地调用构造函数。至于全局和静态对象,会在程序开始时自动调用它们的构造函数,而当程序终止时,会自动调用它们的析构函数。
构造函数和析构函数违反了C语言中“一切工作自己负责”的原则。它们可以使大量的工作在程序运行时被隐式地完成,减轻了程序员的负担。这也违背了C语言的哲学,即语言中的任何部分都不应该通过隐藏的运行时程序来实现。
/*
**编程挑战
*/
/*做一些清理工作
*为Fruit类的析构函数编写函数体,里面包含一条printf()语句,并在一个内层的域中声明一个Fruit类的对象。需要在函数的头部添加#include<stdio.h>语句。然后,重新编译和运行a.out文件,看看当对象离开了它的生命域时是否调用了析构函数。 */
#include <stdio.h>
#include <stdlib.h>
class Fruit {
public: void peel(void); void slice(void); void juice(void);
Fruit(int i, int j); //构造函数
~Fruit(void); //析构函数
private: int weight, calories_per_oz;
};
//构造函数体
Fruit::Fruit(int i, int j) {
weight = i; calories_per_oz = j;
}
//析构函数体
Fruit::~Fruit( void ){
printf( "destructor function is called.\n" );
}
int main( void ){
{
//对象声明时由构造函数进行初始化
Fruit melon(4, 5), banana(12, 8);
}
return EXIT_SUCCESS;
}
输出: