来源:互联网 发布:苹果手机破解软件 编辑:程序博客网 时间:2024/04/29 08:02

类的定义和声明
每个类可以没有成员,也可以定义多个成员,成员可以是数据,函数,或类型别名。
成员函数在内部定义的函数默认是inline。
当我们定义一个类对象时,每个对象具有自己的类数据成员的副本,修改它的数据成员不会改变其他对象的数据成员。
this指针
尽管在员函数内部显式引用this通常是不必要的,但有一种情况必须这么做:当需要将
一个对象作为整体引用而不是引用对象的一个成员时,使用this,该函数返回对调用该函数的对象的引用。
可变数据成员
mutable
const用法
一般常量
const int x=9;
int const x=9;
int const a[5]={1,2,3,4,5]
常对象
<类名> const <对象名>
const <类名> <对象名>
定义常对象时,同样要进行初始化,并且该对象不能被更新。
常指针
定义一个指向字符串的指针常量和定义一个指向字符串常量的指针,const位置不同,
char* const ptr=stringptr;stringptr能更新,ptr所指字符串不能更新。
const *ptr=stringptr;ptr所指字符串不能更新,即stringptr不能更新。
常引用
const <类型说明符> &<引用名>
const double & v1;
常成员函数
<类型说明符> <函数名> (<参数表>) const;
只有常成员函数才能操作常量或常对象,没有使用const说明的成员函数不能用来操作常对象。
类中const数据成员时,只能通过成员初始化列表的方式初始化。
const是加在函数说明后面的类型修饰符,它是函数的一个组成部分,因此,在函数实现部分也要带const。
#include
class R
{
public:
R(int r1, int r2) { R1=r1; R2=r2; }
void print();
void print() const;
private:
int R1, R2;
};

void R::print()
{
cout<<R1<<endl<<R2<<endl;
}

void R::print() const
{
cout<<R1<<endl<<R2<<endl;
}

void main()
{
R a(5, 4);
a.print();
const R b(20, 52);
b.print();
}
static const int b;静态数据成员
const int A::b=10;
const几点用法
1.限定符声明变量只能被读
2.必须初始化
3.可以通过函数对常量进行初始化
4.const的常量值是可以修改的
volatile const int i=0;
int *p=(int*) &i;
*p=100;
const修饰的类数据成员
class A
{
const int size;
}
const数据成员只是在某个对象生存期内是常量,而对于整个类而言确是可变的。不同对象其const数据成员可以不同。所以不能在类声明中初始化const数据成员。
如果想建立在整个类中都恒定的常量,可以用枚举变量实现。
class A
{
enum { size1=100,size2=90};
}
枚举变量不会占用对象的存储空间。
const修饰指针
int b=400;
const int* a=&b;
int const *a=&b;
int* const a=&b;
const int* const a=&b;
const位于*左侧,const修饰指针指向的变量,即指针指向为常量。
const初始化
1非指针const常量初始化
A b;
const A a=b;
2.指针const常量初始化
A* d=new A();
const A* c=d;
或const A* c=new A();
3.引用const常量初始化
A f;
const A& e=f;
const在函数声明中的应用。
1.修饰参数的const。void fun0(const A* a);void fun1(const A& a);
用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,如形参为const A* a,则不能对传递进来的指针的内容进行改变,保护了原指针所指向的内容;如形参为const A& a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。
[注意]:参数const通常用于参数为指针或引用的情况,且只能修饰输入参数;若输入参数采用“值传递”方式,由于函数将自动产生临时变量用于复制该参数,该参数本就不需要保护,所以不用const修饰。
[总结]对于非内部数据类型的输入参数,因该将“值传递”的方式改为“const引用传递”,目的是为了提高效率。例如,将void Func(A a)改为void Func(const A &a)
对于内部数据类型的输入参数,不要将“值传递”的方式改为“const引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x)不应该改为void Func(const int &x)
修饰返回值的const,如const A fun2( ); const A* fun3( );
这样声明了返回值后,const按照"修饰原则"进行修饰,起到相应的保护作用。const Rational operator*(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
}

返回值用const修饰可以防止允许这样的操作发生:Rational a,b;
Radional c;
(a*b) = c;

一般用const修饰返回值为对象本身(非引用和指针)的情况多用于二目操作符重载函数并产生新对象的时候。
[总结]
1. 一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因如下:如果返回值为某个对象为const(const A test = A 实例)或某个对象的引用为const(const A& test = A实例) ,则返回值具有const属性,则返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。
2. 如果给采用“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。如:
const char * GetString(void);
如下语句将出现编译错误:
char *str=GetString();
正确的用法是:
const char *str=GetString();
使用类的成员
在类作用域外,成员只能通过对象或指针分别使用成员访问操作符.或->访问。
一些成员使用成员访问操作符,另一些直接通过类使用作用域操作符(::)访问。一般的数据或函数成员必须通过对象来访问。
函数返回类型不一定在类作用域中
与形参类型相比,返回类型出现在成员名字前面。如果函数在类定义体外定义则用于返回类型的名字在类作用域外。如果返回类型使用由类定义的类型,则必须使用完全限定名。
class Screen
{
public:
typedef string::size_type index;
index get_cursor() const;
}
inline Screen::index Screen::get_cursor() const
{
}
类的成员函数的形参与类的数据成员名称最好不一样。
初始化的次序通常无关紧要。如果一个成员是根据其他成员而初始化,则次序很重要。
友元可以是普通的非成员函数,或前面定义的其他类的成员函数,或整个类。
static类成员
每个类数据成员独立于该类的任意对象而存在,每个static数据成员是与类关联的对象,并不与该类的对象关联。
类也可以定义static成员函数。static没有this形参,它可以直接访问static成员,但不能使用非static成员。


复制构造函数具有单个形参,该形参(通常用const修饰)是对该类对象的引用。但定义一个新对象并用一个同类型的对象对他进行初始化是,将显式调用复制构造函数。当将该类型的对象传递给函数或从函数返回该类型的对象时,将隐式调用复制构造函数。
复制构造函数可用于:
.根据另一个同类型的对象显式或隐式初始化一个对象
.复制一个对象,将它作为实参传给一个函数
.从函数返回时复制一个对象
.初始化顺序容器中的元素。
.根据元素初始化式列表初始化数组元素原对象的副本。
C++支持两种初始化形式:直接初始化和复制初始化。复制初始化用=符号,而直接初始化将初始式放在圆括号中。
对于类类型对象时,两种初始化有所不同:直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象。
合成的复制构造函数
如果我们没有定义复制构造函数,编译器会为我们合成一个。与合成的默认构造函数不同,即使我们定义了其他构造函数,也会合成复制构造函数。合成复制构造函数的行为是,执行逐个成员初始化。将新对象初始化。
所谓逐个,指的是将现有对象的每个非static成员,依次复制到正创建的对象。
复制构造函数就是接受单个类类型引用形参(常用const修饰)的构造函数。
只包含类类型成员或内置类型(但不是指针)成员的类,无须显式的定义复制构造函数,也可以复制。
禁止复制
有些类需要完全禁止复制,类必须显式声明其复制构造函数为private。
赋值操作符的返回类型应该与内置类型赋值运算返回的类型相同。内置类型的赋值运算返回对右操作数的引用。因此,赋值操作符也返回对同一类类型的引用。
class A
{
public:
A& operator=(const A&)
};

合成赋值操作符
合成赋值操作符与合成赋值构造函数的操作类似。它会执行逐个成员赋值:
A::operator=(const A &a)
{
isbn=a.isbn;
revenue=a.revenue;
return *this
}
合成赋值操作符根据成员类型使用合适的内置或类定义的赋值操作符,依次给每个成员赋值,改操作符返回*this,它是对左操作数对象的引用。
析构函数
1.何时调用析构函数
撤销类对象时会自动调用析构函数
A *P=new A;
{
A(*P);
delete p;
}
动态分配的对象只有在指向该对象的指针被删除时才撤销。如果没有删除指向动态对象的指针,则不会运行该对象的析构函数,对象就一直存在,从而导致内存泄露,而且,对象内部使用的任何资源也不会释放。
如果类需要析构函数,则它也需要赋值操作符和复制构造函数,这是三法则。指的是如果需要析构函数,则需要所有这三个复制控制成员。
管理指针成员

 

 

 

 


 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我真的爱上你了怎么办 弯腰时间久了腰疼怎么办 斗鱼pk输的怎么办 领导当着人骂我怎么办 被老板骂了应该怎么办 三星s7关机键掉了怎么办 主播遇到黑粉怎么办 在工作单位突然死亡怎么办 孕7月半夜脚抽筋怎么办 上单对上两个射手怎么办 游戏本玩游戏掉帧怎么办 手机开直播很卡怎么办 小孩小鸡被虫子咬了怎么办 小鸡仔不吃食了怎么办 小鸡的腿瘸了怎么办 在境外住酒店钱被偷了怎么办 一加6屏幕辣眼睛怎么办 棉质衣服皱了怎么办 洗完衣服皱了怎么办 穿衬衫袖子很皱怎么办 洗完衣服有褶皱怎么办 麻料裤子容易皱怎么办 苹果手机邮件删了怎么办 飞猪12306登录不上怎么办 邮箱被别人绑定12306怎么办 白名单一个地址也没怎么办 12306忘记用户名和密码怎么办 12306忘了用户名和密码怎么办 12306注册后忘了密码怎么办 12306帐号忘了密码怎么办 12306忘了密码和手机号怎么办 12306账号密码邮箱忘了怎么办 注册12306账号没有邮箱怎么办 12306忘了用户名和邮箱怎么办 12306忘记用户名和邮箱怎么办 12306证件号码已被注册怎么办 12306忘记手机号和邮箱怎么办 发邮件被对方服务器退回怎么办 铁路12306显示已注册怎么办 qq密码太长输不进去怎么办 淘宝买家收货地址填写不全怎么办