数据抽象----类(c++)

[程序设计教程用c++语言编程陈家骏]
1.类的定义
a.创建对象前,类中说明的数据成员不占内存空间,类定义中说明数据成员(某些静态成员除外)时不能赋初值,它们初始化 应在构造函数中指出。数据成员类型可以使任意C++类型(包括类,void除外),说明一个数据成员时,如果未见到相应的类型定义或相应的类型未定义完,则该数据成员只能是这些类型的指针或引用类型。
b.把成员函数放在类定义中是建议编译程序按内联函数处理它们。一般定义放在.h文件中,类外定义的成员函数放在实现文件.cpp中。
c.成员的访问控制:信息隐藏
(1)public:public成员访问不受限制,程序中任何地方都可以访问一个类的public成员
(2)protected:只能在本类、派生类、友元中访问。
(3)private:只能在本类和友元中访问。
d.友元:C++类定义中,可以指定某个全局函数、某个其他类或某个其他类的成员函数直接访问该类的private和protected成员,分别成为友元函数、友元类、友元类成员函数,统称友元。友元声明可以放在类中任何地方。友元不是类的成员函数,但可以访问类中的非公有成员。友元不具有传递性。
2.this指针:对于类的数据成员(静态成员除外),类对象都有一个拷贝,每个对象都有一块内存空间,分别存储它们的数据成员,而类中成员函数对该类的所有对象只有一个拷贝,成员函数通过隐藏的this指针访问类成员。当通过对象调用类的成员函数时,编译程序会把相应的对象的地址作为隐含的参数传给成员函数的隐藏的形参this。在成员函数中要把对象作为整体来操作(如取对象的地址),则必须显式地使用this指针
3.构造函数:如果类中没有提供任何构造函数,编译程序在需要时会隐式为之提供一个默认构造函数,该默认构造函数不做任何事情,负责调用成员对象雷和基类的构造函数以及实现其他一些功能。在对象类提供了构造函数的情况下,即使对象没有提供默认构造函数,编译程序也不再为其提供默认构造函数。构造函数一般是public的,有时也为priavte,作用是限制创建该类对象的范围,只能在友元和本类中创建该类对象。
4.常量数据成员和引用数据成员:不能在说明它们时初始化,也不能采用赋值操作对它们初始化,可采用成员初始化表进行,当类中有常量数据成员或引用数据成员时,如果类中定义了构造函数,则要在所有构造函数 的成员初始化表中对它们进行初始化,如果类中没有定义构造函数,则编译程序不会给该类生成一个默认的构造函数(编译器生成的默认构造函数不会对类的常量数据成员和引用数据成员进行初始化),这样的类程序时不能用于创建对象的。数据成员的初始化顺序是根据类中的说明顺序而不是在成员初始化列表中的书写顺序。
5.指针空间:创建对象时,系统会为对象分配一块内存空间存储对象数据成员。但对于指针数据成员来说,系统只分配了存储该指针所需的空间,没有分配指针所指向的空间,对象自己需要申请,对象消亡时,系统收回的只是指针本身的存储空间,指针指向的空间需要对象自己归还。
6.成员对象:创建包含成员对象的对象时,对成员对象的初始化是由成员对象的构造函数来实现的,默认情况下,成员对象由成员对象的默认构造函数进行初始化,如果调用成员对象类的非默认构造函数对成员对象初始化,则要在包含成员对象的类的构造函数成员初始化表中指出,如:
class A
{
 int m;
public:
 A()
 {m=0;}
 A(int m1)
 {m=m1;}
};
class B
{
 int n;
 A a;
public:
 B()
 {n=0;}
 B(int n1)
 {n=n1;}
 B(int n1, int m1):a(m1)
 {n=n1;}
};
B b1,b2(1);  //b1,b2的成员对象a均由A类的默认构造函数初始化
B b3(1,2);  //调用A类带int参数的构造函数对b3的a进行初始化。
实际上,编译程序把成员初始化表中对成员对象的初始化描述编译成对成员对象构造函数的调用指令。在创建含有成员对象的类的对象时,首先调用本身类的构造函数,在进入本身类的构造函数的函数体之前,调用成员对象的类的构造函数,再执行本身构造函数的函数体。即使成员初始化表为空,只要类中有成员对象,编译程序会生成对成员对象的默认构造函数调用。当一个对象包含多个成员对象时,按照类中定义顺序而非初始化表中描述顺序执行。当包含成员对象的对象消亡时,先调用本身类的析构函数,本身类的析构函数的函数体执行完后,再调用成员对象类的析构函数,如果有多个成员对象,则成员对象析构函数的调用次序与它们的构造函数调用次序正好相反。
7.拷贝构造函数:创建一个对象时,可以用同类一个对象对其初始化,即为拷贝构造函数,其原型为:<类名>([const] <类名>&);,也可有其他参数,但这些参数必须有默认值,一般来讲,如下三种情况会调用拷贝构造函数:
a.定义对象时
A a1;  //默认构造函数初始化
A a2(a1);  //拷贝构造函数初始化,也可写成:A a2=a1;  或 A a2=A(a1);
b.对象作为参数传给函数时
void f(A x);
A a;
f(a);  //调用时将创建形参x,调用拷贝构造函数用a对其初始化
c.对象作为返回值
A f()
{
A a;
……
return a;  //创建一个a的临时对象,调用拷贝构造函数对其初始化
}
如果类定义中没有给出拷贝构造函数,编译程序会隐式提供一个拷贝构造,逐个成员拷贝初始化,对普通成员,采用通常的初始化,对对象成员,调用对象类的拷贝构造函数实现成员对象的初始化(递归定义)。一般编译程序提供的拷贝构造函数足以满足要求,类中不需显式定义,不过有时需要显式定义,如:
class  A
{
 int x;
 char *p;
public:
 A(char *str)
 {x=0;
 p=new char(strlen(str)+1);
 strcpy(p,str);
 }
 ~A()
 {delete [] p;}
};
A a1("abcd");
A a2(a1);
系统的默认构造函数将会使a1和a2的p指向同一块内存区,一个对象修改后,另一个对象会受影响,消亡时,同一块内存区会归还两次,导致程序运行异常。可在类中显式定义拷贝构造函数。当类中包含成员对象时,成员对象的拷贝初始化可由成员对象类的拷贝构造函数来实现,系统提供隐式拷贝构造函数会去调用成员对象的拷贝构造函数。而自定义拷贝构造函数不会去调用成员对象的拷贝构造函数,必须在拷贝构造函数的成员初始化表中显式给出
8.const成员函数:在const成员函数定义的地方,告诉编译器该产业函数不应该改变对象数据成员的值,使用(调用)const成员函数的地方,告诉编译程序不会改变对象数据成员的值。当const成员函数放在类外定义是,声明和定义都要加上const修饰。常量对象只能调用const成员函数,不能调用非const成员函数。
9.静态成员:解决同一个类的数据共享问题。static数据成员必须在类定义体的外部定义(正好一次),不像普通数据成员,static成员不是通过类构造函数初始化,而是在定义时初始化。类中声明时需要static关键字,类外定义时,不需要static关键字。对于const static成员,可以再类定义体中进行初始化,值为常量表达式,但该数据成员仍必须在类外部定义,定义时不需指定初始值。static成员函数没有this形参,可以直接访问所属类的static成员,不能直接使用非static成员。static成员函数不能声明为const,不能声明为虚函数。static成员函数只能访问static数据成员和static成员函数。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值