1 类和对象
1.1 声明类
和变量、函数一样,类也需要声明。要声明类,可使用关键字class,并在其后依次包含
- 类名
- 一组放在{}内的成员属性和成员函数
- 结尾的分号
类声明将类本身及其属性告诉编译器。类声明本身并不能改变程序的行为,必须使用类,就像需要调用函数一样
class Human
{
//成员属性
string name;
int age;
//成员函数
void setAge();
}
通过关键字class,C++提供一种功能强大的方式,让我们可以创建自己的数据类型,并在其中封装属性和使用属性的函数(方法),类的所有属性以及在其中声明的函数都是类的成员。
封装是指将数据及使用它们的函数进行逻辑编组,这是面向对象编程的重要特征
1.2 对象
仅声明类并不会对程序的执行产生影响。要使用类的功能,通常需要创建其实例--对象,并通过对象访问成员方法和属性
1.3 访问对象成员
1.3.1 句点运算符(.)
句点运算符既可以用来访问对象属性也可以访问对象方法。
Human firstMan;
firstMan.age=26;
firstMan.setAge();
1.3.2 指针运算符(->)
如果对象是使用new实例化的,或者有指向对象的指针,则可使用指针运算符(->)来访问成员属性和方法:
Human* firstWoman=new Human();
firstWoman->name="Alice";
firstWoman->setAge();
delete firstWoman;
2 类的保护属性:public和private
C++可以将成员声明为公有的,这在有了对象后即可获取它们;也可以声明为私有的,意味着只能在类的内部({}之间声明的成员)或其友元中访问。
假如有这样一个类:
class Human
{
private:
//私有成员数据
string name;
int age;
public:
int getAge(){
return age;
}
void setAge(int humansAge){
age=humansAge;
}
}
假如有一个名为eve的Human实例:
Human eve;
如果试图使用下述代码访问成员age:
cout<<eve.age;
将出现编译错误,要访问age的唯一途径就是通过Human类的公有方法getAge()。
保护属性可以让程序员决定要暴露哪些属性及如何暴露这些属性(比如在方法getAge()中,返回一个虚假的年龄)。
总之,C++让类的设计者能够控制类属性的访问和操作方式
3 构造函数
构造函数是一种特殊的函数,在根据类创建对象时被调用。
3.1 声明和实现构造函数
构造函数与类同名且没有返回值。构造函数既可以在类声明中实现(定义),也可以在类声明外实现。
类声明内实现:
class Human
{
public:
Human(){
//构造函数代码
}
};
类声明外实现:
class Human
{
public:
Human(); //构造函数声明
};
Human::Human(){
//构造函数代码
}
::被称为作用域解析运算符。Human::age表示在Human类中声明的变量age,而::age表示全局作用域中的变量age
3.2 何时及如何使用构造函数
构造函数在创建对象时被调用,所以一般会在构造函数中初始化类成员变量。
可在不提供参数的情况下调用的构造函数称为默认构造函数。默认构造函数是可选的,如果声明类时没有提供默认构造函数,编译器将自动创建一个,这种构造函数会创建成员属性,但不会将POD类型的属性初始化为非零值。
3.3 重载构造函数
与函数一样,构造函数也可以重载,下面将创建一个将姓名作为参数的构造函数。
class Human
{
public:
Human(){
//默认构造函数实现
}
Human(string humansName){
//重载的构造函数实现
}
};
当然也可以不实现默认构造函数,从而要求实例化对象时必须提供某些参数。没有默认构造函数并且类的设计者提供了重载的构造函数时,C++编译器将不会生成默认构造函数
3.4 带默认值的构造函数
构造函数也可以有带默认值的参数,用法和普通的带默认值函数一样。
class Human
{
private:
int age;
string name;
public:
//重载构造函数(没有默认构造函数)
Human(string humansName, int humansAge = 25)
{
name=humansName;
age=humansAge;
}
};
实例化这个类时可以使用以下语法:
Human adam("Adam");
Human eve("eve",18);
默认构造函数是调用时可不提供参数的构造函数,而并不一定是不接受任何参数构造函数,下面的构造函数虽然有两个参数,但它们都有默认值,因此也是默认构造函数:
class Human
{
private:
int age;
string name;
public:
//有两个参数的默认构造函数
Human(string humansName=“Adam", int humansAge = 25)
{
name=humansName;
age=humansAge;
}
};
3.5 初始化列表
TODO...
4 析构函数
TODO...
5 复制构造函数
7 this指针
this指针是一个特殊的指针,它指向当前对象的实例,每一个对象都能通过this指针访问自己的地址。
this指针是一个隐藏的指针,可以在类的成员函数中使用,用来指向调用对象。当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为this指针。
友元函数没有this指针,因为友元函数不是类的成员,只有成员函数才有this指针
class Human
{
private:
void Talk(string statement){
cout<<statement;
}
public:
void introduceSelf(){
Talk("bla bla");
}
}
实际上,编译器在调用Talk时嵌入this指针,即Talk(this,"bla bla")
调用静态方法时,不会隐式传递this指针,因为静态函数不与类实例相关联,而由所有实例共享。要在静态函数中使用实例变量,应显示的声明一个形参,并将实参设置为this指针