C++类

类的数据成员可以分为公有成员变量,私有成员变量和保护成员变量。公有成员变量可以供外部和内部使用,私有成员变量只供类内部使用,而保护成员变量可供类的内部使用,也可以供子类使用。

友元函数

友元函数是可以直接访问类的私有成员的非成员函数,它是定义在在类外的普通函数,它不属于任何类,但是需要在类的定义中加以声明,声明时需要在友元的名称前加上friend,格式如下:

friend <类型> <函数名><形式参数>;

友元函数的声明既可以放在私有部分,也可以放在公有部分,是没有区别的。

友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类的私有成员和保护成员。

const对象和const成员函数

const 关键字修饰变量或者函数时,其意思通常是只读。比如,当const关键字修饰变量时,变量的值不能改变,当const修饰成员函数时,此函数不能更改类中的数据成员的值。

(1)常引用。用const关键字修饰,常引用所引用的 对象不会被更新,如果常引用用作形参,便不会引起对实参的更改,声明常引用的方式:

const <类型说明符>&<引用名>

(2)常成员函数

const<类名><对象名>

其中,常成员函数不能更改对象中数据成员的值,也不能调用非类常成员函数

如果将对象声明为常对象,那么这个对象只能调用常成员函数

对于常成员函数,后面的const关键字可以作为重载函数的区分

隐含的this指针

this指针是隐含在每个类成员函数的指针,其指向正在操作此函数的类对象。this指针的作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员时,编译器会自动将对象本身的地址作为一个隐含的参数传递给函数。

类的静态成员函数没有this指针。

静态类成员

静态数据成员可以被所有的类对象共享。声明一个静态数据变量只需要在前面加static关键字。非静态数据成员随着对象的创建而被多次创建和初始化,而静态数据成不同于非静态的数据成员,一个类的静态数据成员仅创建和初始化一次,且在程序开始执行时创建,然后被该类的所有对象共享。

静态的数据成员能够被类的成员函数访问,但不能在构造函数中初始化。这时因为静态数据成员在构造函数调用之前就已经存在了。静态数据成员可以在定义时初始化,且必须在类和所有的成员函数之外。

与静态数据成员类似,静态成员函数被所有的对象共享,且静态成员函数不属于对象,而是属于某个类,静态成员函数没有this指针。静态成员函数在类外调用方式

<类名>::<成员函数名>(实参表)

指向类成员的指针

指向数据成员的指针

指向非静态数据成员的指针定义格式

<数据类型><类名>::*<指针名>[=&<类名>::<非静态数据成员>]

指向非静态数据成员的指针在定义时必须和类关联,在使用时必须和具体的对象关联。

<类对象名>.*<指向非静态数据成员的指针>

指向静态数据成员的指针的定义和使用与普通指针相同,在定义时无须和类关联,在使用时也无须和具体的对象相关联。

定义一个指向非静态成员函数的指针必须要注意3个方面与其指向的类成员函数保持一致,即参数列表、返回类型和所属的类要相同。定义格式如下:

<数据类型>(<类名>::*<指针名>)(<参数列表>)[=&<类名>::<非静态成员函数>]

使用指向非静态成员函数的指针方法和使用指向非静态数据成员的指针的方法相同,格式如下:

(<类对象名>.*<指向非静态成员函数的指针>)(<参数列表>);

指向静态成员函数的指针和普通指针相同,在定义时无须和类关联,在使用时也无须和具体的对象相关联。

<数据类型>(*<指针名>)(<参数列表>)[=&<类名>::<静态成员函数>]

构造函数的函数名必须与类名相同,而且没有返回值,构造函数通常被声明为公有函数,只要类中国有了构造函数,编译器就会在建立新对象的地方自动插入对构造函数的调用代码。因此通常说构造函数在对象创建时将被自动调用。

拷贝构造函数是一种特殊的构造函数,具有一般构造函数的所有特性,其形参是本类的对象的引用。其作用是使用一个已经存在的对象去初始化同类的另一个新对象。

拷贝构造函数由编译器调用来完成一些基于同一类的其他对象的构建及初始化。其唯一的参数(对象的引用)是不可变的(const类型)。拷贝构造函数需要调用基类的拷贝构造函数和成员函数。

普通构造函数是在对象创建时被调用,而拷贝构造函数在以下三种情况下被调用:

(1)当用类的一个对象去初始化改类的另一个对象时

int main()
{
Point A(2,3);
Point B(A);
cout<<B.Get()<<endl;
return 0;
}

(2)如果函数的形参是类的对象,调用函数时,进行形参和实参复制时。例如

void fun(Point pt)
{
cout<<pt.GetX()<<endl;

}
int main()
{
 Point A(2,3);
 fun(A);
 return 0;
}

(3)如果函数的返回值是类的对象时,函数执行完成返回调用者时。例如:

Point fun()
{
 Point pt(2,3);
 return pt;
}
int main()
{
 Point B;
 B=fun();
}

拷贝构造函数不可以改变它所引用的对象,其原因为:当一个对象以传递值的方式传入一个函数时,拷贝构造函数自动地被调用来生成函数中的对象。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用出来拷贝这个对象,这样拷贝才可以传入它自己的拷贝构造函数,这会导致无限循环直至栈溢出。

深拷贝和浅拷贝

假如在类中没有显式地声明一个拷贝构造函数,那么,编译器会自动生成一个默认的拷贝构造函数,该拷贝构造函数完成对象之间的位拷贝,也被称为浅拷贝。

假如一个类拥有资源,当这个类的对象发生复制过程时,资源重新分配,这个过程叫做深拷贝,反之,没有重新分配资源,就是浅拷贝。

C++语言的基本规则是:创建一个派生类的对象时,如果基类带有构造函数,则先调用基类的构造函数,然后才调用派生类的构造函数。虚基类的构造函数在任何非基类构造函数前调用,如果构造函数中包括多个虚基类,他们的调用顺序以声明顺序为准。如果虚基类是由非虚基类派生而来的,那么非虚基类的构造函数先被调用。

delete操作符只能清空堆空间,而不能清除栈空间,如果强行清楚栈空间内存,将导致程序崩溃。

虚析构函数是为了解决这样一个问题:基类的指针指向派生类对象,并用基类的指针删除派生类对象。

当且仅当类中包含至少一个虚函数时才去声明虚析构函数。抽象类时准备被用作基类的,基类必须要有一个析构函数,纯虚寒素会产生抽象类,所以:在想称为抽象类的类里声明一个纯虚析构函数。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Estelle_Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值