OOP课程笔记:第一章 类和对象
第一章 类和对象
1.基本概念
对象是由一组属性(attribute)和一组行为(behavior)构成的。
在C++中,每个对象都是由数据和函数(即操作代码)这两部分组成的。
面向对象程序设计中每一组数据都是有特定的用途的,是某种操作的对象。也就是说,一组操作调用一组数据。
把相关的数据和操作放在一起,形成一个整体,与外界相对分隔。这就是面向对象的程序设计中的对象。
在C++,中对象的类型称为类(class)。类代表了某一批对象的共性和特征。类是对象的抽象,而对象是类的具体实例(instance)。
class Student{
private :
char Name[20];
float Math;
float Chinese;
public :
float average;
void SetName(char *name);
void SetMath(float math);
void SetChinese(float ch);
float GetAverage(void);
}; // 分号注意不要少2.关键字
| 关键字 | 成员类型 | 作用域 |
|---|---|---|
| private | 私有成员 | 只允许该类内的成员函数使用私有的成员数据 |
| public | 公有成员 | 可以在类内或类外自由使用 |
| protected | 保护成员 | 仅允许该类及该类的派生类 |
3.类的成员
如果未加说明,类中成员默认的访问权限是private,即私有的。
在下示例中,在类外不能直接使用 x 或 y ,必须通过 Setxy()给 x 或 y 赋值,通过 Print() 输出 x 或 y 。
class A{
float x, y;
public:
void Setxy(float a, float b){
x = a;
y = b;
}
void Print(void){ cout << x << ‘\t’ << y << endl;}
};成员函数与成员数据的定义不分先后,可以先说明函数原型,再在类体外定义函数体。
class A{
float x, y;
public:
void Setxy(float a, float b); // 体内声明函数
void Print(void);
};
void A::Setxy(float a, float b){ // 体外定义
x = a;
y = b;
}
void A::Print(void){
cout << x << '\t' << y << endl;
}注意两点 :
1.类具有封装性,并且类只是定义了一种结构,所以类中的任何成员数据均不能使用关键字 extern , auto 或 register 限定其存储类型。
2.在定义类时,只是定义了一种导出的数据类型,并不为类分配存储空间,所以,在定义类中的数据成员时,不能对其初始化。
class Test {
int x = 5,y = 6; // 是不允许的
extern float x; // 是不允许的
};struct 与 class
在C++语言中,结构体类型 struct 只是类 class 的一个特例。
结构体类型与类的唯一的区别在于:在类中,其成员的缺省的存取权限是私有的;而在结构体类型中,其成员的缺省的存取权限是公有的。
内联成员函数
当我们定义一个类时,可以在类中直接定义函数体。这时成员函数在编译时是作为内联函数来实现的。
同时,我们也可以在类体外定义类的内联成员函数,在类体内声明函数
在类体外定义时,在成员函数的定义前面加上关键字 inline 。
class A{
float x, y;
public:
void Setxy(float a, float b); // 声明内联函数
void Print(void);
};
inline void A::Setxy(float a, float b){ // 定义内联函数
x = a;
y = b;
}
inline void A::Print(void){ cout << x << 't' << y << endl;}4.对象
在定义类时,只是定义了一种数据类型,即说明程序中可能会出现该类型的数据,并不为类分配存储空间。
类的变量我们称之为对象,对象是类的实例。
在建立对象时,只为对象分配用于保存数据成员的内存空间,而成员函数的代码为该类的每一个对象所共享。
对象的使用
一个对象的成员就是该对象的类所定义的成员,有成员数据和成员函数,引用时同结构体变量类似,用 . 运算符。
class A{
float x, y;
public:
float m, n;
void Setxy(float a, float b){
x = a;
y = b;
}
void Print(void){ cout << x << '\t' << y << endl; }
};
void main(void){
A a1, a2; // 定义对象
a1.m = 10;
a1.n = 20; // 为公有成员数据赋值
a1.Setxy(2.0, 5.0); // 为私有成员数据赋值
a1.Print();
}访问私有成员
用成员选择运算符 . 只能访问对象的公有成员,而不能访问对象的私有成员或保护成员。
若要访问对象的私有的数据成员,只能通过对象的公有成员函数来获取。
class A{
float x, y;
public:
float m, n;
void Setxy(float a, float b){
x = a;
y = b;
}
void Print(void){ cout << x << '\t' << y << endl; }
};
void main(void)
{
A a1, a2;
a1.m = 10;
a1.n = 20; // 为公有成员数据赋值
a1.x = 2; // 非法,私有成员不可以在类外访问
a1.y = 5; // 非法,私有成员不可以在类外访问
a1.Setxy(2.0, 5.0);
a1.Print();
}同类型的对象之间可以整体赋值,这种赋值与对象的成员的访问权限无关。
class A{
float x, y;
public:
float m, n;
void Setxy(float a, float b){
x = a;
y = b;
}
void Print(void){ cout << x << '\t' << y << endl; }
};
void main(void){
A a1, a2;
a1.m = 10;
a1.n = 20;
a1.Setxy(2.0, 5.0);
a2 = a1; // 同类型对象赋值,相当于成员数据之间相互赋值
a1.Print();
a2.Print();
}类的作用域
类体的区域称为类作用域。类的成员函数与成员数据,其作用域都是属于类的作用域,仅在该类的范围内有效。
class A{
float x, y;
public:
float m, n;
void Setxy(float a, float b){
x = a;
y = b;
}
void Print(void) { cout << x << '\t' << y << endl;}
};
void main(void){
A a1, a2;
a1.m = 20;
a1.n = 10;
a1.Setxy(2.0, 5.0); // 类的作用域内
a1.Print(); // 类的作用域内
Setxy(2.0, 5.0); // 不允许
Print(); // 不允许
}对象的作用域
分为全局对象、局部对象、局部静态对象等。
class A // 文件作用域,整个文件有效
{
float x, y;
public:
float m, n;
void Setxy(float a, float b){
x = a;
y = b;
}
void Print(void){
cout << x << '\t' << y << endl;
}
} a3, a4;
void main(void){
A a1, a2;
class B{ // 块作用域,在函数内有效
int i, j;
public:
void Setij(int m, int n){
i = m;
j = n;
}
};
B b1, b2;
a1.Setxy(2.0, 5.0);
b1.Setij(1, 2);
}类的嵌套
类B包含在类A中,为嵌套定义。
在类 A 的定义中,并不为 b1 , b2 分配空间,只有在定义类 A 的对象时,才为嵌套类的对象分配空间。嵌套类的作用域在类 A 的定义结束时结束。
class A{
class B{
int i, j;
public:
void Setij(int m, int n){
i = m;
j = n;
}
};
float x, y;
public:
B b1, b2; // 嵌套类的对象
void Setxy(float a, float b){
x = a;
y = b;
}
void Print(void){
cout << x << '\t' << y << endl;
}
};5.成员函数
成员函数的重载
成员函数可以带有缺省的参数,也可以重载成员函数。
重载时,函数的形参必须在类型或数目上不同。
class Test{
int x, y;
int m, n;
public:
void Setxy(int a, int b){
x = a;
y = b;
}
void Setxy(int a, int b, int c, int d){
x = a;
y = b;
m = c;
n = d;
}
void Printxy(int x) { cout << “m = "<<m<<'\t'<<“n=" << n << endl; }
void Printxy(void) { cout << "x=" << x << '\t' << "y=" << y << endl; }
};
void main(void)
{
Test p1, p2;
p1.Setxy(3, 5);
p2.Setxy(10, 20, 30, 40); // 参数不同
p1.Printxy();
p2.Printxy();
p2.Printxy(2); // 参数类型不同
}使用指针引用对象成员函数
class A{
float x, y;
public:
float Sum(void) { return x + y; }
void Set(float a, float b){
x = a;
y = b;
}
void Print(void) { cout << "x=" << x << '\t' << "y=" << y << endl; }
};
void main(void)
{
A a1, a2;
A *p; // 定义类的指针
p = &a1; // 给指针赋值
p->Set(2.0, 3.0); // 通过指针引用对象的成员函数
p->Print();
cout << p->Sum() << endl;
a2.Set(10.0, 20.0);
a2.Print();
}6.this指针
不同对象占据内存中的不同区域,它们所保存的数据各不相同,但对成员数据进行操作的成员函数的程序代码均是一样的。
当对一个对象调用成员函数时,编译程序先将对象的地址赋给 this 指针,然后调用成员函数,每次成员函数存取数据成员时,也隐含使用this指针。
this 指针具有如下形式的缺省说明,实际上是一个常量指针
class classname{};
classname *const this; // this实际上是一个常量指针以一个字符串的类作为示例代码
class S{
public:
char *strp;
int length;
void Ini(char *s);
void Print(void);
void Copy(S &s);
};
void S::Copy(S &s){
if (&s == this) // this 指针和传入的待复制的类进行比较
cout << "不能复制本身\n ";
else{
if (strp)
delete[] strp;
length = s.length;
strp = new char[length + 1];
strcpy(strp, s.strp);
}
}
评论已关闭