分享
 
 
 

c++入门学习笔记--类和对象

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

自己的学习笔记,C++中关于对象和类的说明

I

***类,多么富有艺术性的词!想一想能把真实世界中的一切在它中模拟实现,就让人兴奋不已。掌握了它也就掌握了程序艺术的真谛、也就掌握了打通了现实与虚幻的时空门!---Skyala***

Skyala请您记住下面惊人的相似规律:

人(类)->父母(对象)->子女(继承、多重继承)->子孙(多态性)---哇,My God!多么完美的曲线!

面向对象程序设计总结:向对象发送消息。

可以减少函数传递过程中的参数

建立的类要有用,实用为准!

一、类杂谈

1。定义:

类:对实体的属性和行为的一般描述。Skyala注:太完美的概念是定义不来的

是程序设计中的基本单位。可以说是一种新的数据类型,所以有这么多的面向对象程序设计语言。太灵活了

类的数据部分:数据成员(data member) ,其初始化不能在定义体中声明它们的地方初始化,而应该用类的构造函数初始化或给它们设置值的函数赋值。

最好保持类的所有数据成员都是私有的,提供函数来操作这些数据,可隐藏类的实现、减少错误,提高可修改性。

外部不能访问类的私有成员,只能利用成员函数。记住main也是一个类的外部

类的函数部分:成员函数(member function),在外部访问类公有成员函数,也要用来成员访问运算符

对象:由类产生的大量的项称为对象也即“存储的一个区域”

对象是类的最终实例化。

对象初始化 Time T(23)在对象名右,分号前的圆括号中

类是C中结构的自然延伸。

2。类的成员访问运算符:

圆点:通过对象名或对对象的引用访问 p.t

箭头:通过指向对象的指针访问 p->t

4。构造函数与析构函数

a.与类同名的成员函数叫“构造函数(constructor)”,用来初始化类的对象的数据成员。

构造函数:没有返回类型--所以没有返回值,可重载

给构造函数提供默认参数值即使调用构造函数时没有提供参数值,也会确保按默认参数初始化。所有的参数都是默认参数的也是默认构造函数。

不要在构造函数中调用其它函数(虽然这是允许的)但在初始化正确地完成之前使用数据成员可能会导致错误

b. 与类同名但加了“~”(按位取反运算符)的成员函数叫“析构函数(destructor)”,系统回收内存前 做清理工作

析构函数:没有返回类型--所以没有返回值,不能重载--所以在类中只有一个

c.在对象的建立和撤销时分别自动调用相应的构造和析构函数,两者的调用顺序正好相反

根据对象的不同:全局作用域(程序终止)、局部对象(声明对象的程序块)、静态static局部对象(程序终止,但在全局前)

5。 接口和实现

类的定义:包括数据成员和成员函数的声明,引处的成员函数声明也即函数的原型。

要用分号结束类的定义

接口:类的公有函数(访问说明符public中的函数)提供的操作该类的数据成员的方法,此种函数也叫接 口

把类的声明放入某个头文件中构成类的公有接口

实现:类的成员函数的定义部分,在外部定义的要用双目运算符“::”使用成员函数,

把成员函数的定义放入某个源文件中,从而构成类的实现--信息隐藏

用户可以访问类的接口,便不能访问类的实现

好处:只要接口没变,实现改变了只要使用类的代码重新编译而不需改动。

**注软件工程的基本原则:

最低访问权原则:(当然相对于用户了--类的使用者)

除了很小的函数外,所有的成员函数都应在类定义体外定义,有利于接口和实现分离。能鼓励独立软件销售商(ISV)类库作为商品 ---Skyala:全部行业有公用类,统一规化软件类库,多么有趣的一件事

6。一个成员函数中类的内部定义的会自动成为内联函数(inline),外部的要加inline。

7。防止多次包含相同的头文件time.h为头文件名,TIME为假设的类,"_"代替".",此处运用了预处理指令

#ifndef TIME_H

#define TIME_H

.

.

#endif

8。公有(Public)、私有(private)、受保护(protected)

私有数据成员只能被本类的成员函数或类的友元访问

类的默认情况下是私有访问类型

9。访问函数及工具函数

set 设置函数,可进行合法性检查。get 获取函数的地位。

不仅有助于保护数据的完整性,而且也使得数据成员的实现方式对客户隐藏起来

10。不要让公有成员函数返回对私有数据成员的非常量引用(或指针)

如下:

public:

int &badset();

int Time::badset(inthh)

{

return hour;

}

T.badset(12) = 74; //返回的引用函数调用可作左值。

11。“=”可以将一个类赋值给同类型的另一个类,通过逐个成员拷贝的默认赋值方式实现的

应用举例:LeapYear.h、LeapYear.cpp

注:这是个闰年的计算,不过本人不满意,有点儿乱。

编译环境:Window2000 Vc6.0

#ifndef LEAPYEAR_H //预处理指令,防止包含多个同名头文件

#define LEAPYEAR_H //"-"代替"."

class LeapYear

{

public:

//可以给构造函数提供默认参数,无返回值无返回类型

LeapYear (int, int, int);

~LeapYear ();

int getYear ();

void setMonth (int);

int getDay ();

void print () const; //const成员函数

private:

int iYear;

int iMonth;

//int iday; 要注意大小不要输入错误

int iDay;

int checkDay (int); //工具函数

}; //类定义结束

#endif

#include <iostream>

#include <string>

#include "LeapYear.h"

using namespace std;

//成员初始化

LeapYear::LeapYear (int iY, int iM ,int iD)

{

iMonth = iM;

iYear = iY;

//iDay = checkDay (int iD); //函数调用格式错误

iDay = checkDay (iD);

cout << "constructor sucessed!" << endl;

}

LeapYear::~LeapYear()

{

cout << "对象内存释放成功!" << endl;

}

int LeapYear::getYear ()

{

return iYear;

}

void LeapYear::setMonth (int iM)

{

iMonth = (iM < 12 && iM > 1)?iM: 1;

}

int LeapYear::getDay ()

{

return iDay;

}

int LeapYear::checkDay (int testDay)

{

static int dayPerMonth [13] ={0, 31, 28, 31,30,

31, 30, 31, 31,

30, 31, 30, 31};

if (iMonth != 2)

{

if (testDay > 0 && testDay <= dayPerMonth [iMonth])

return dayPerMonth [iMonth];

}

else

{

//闰年计算公式

int days = (iYear % 400 == 0 ||

(iYear % 4 == 0 && iYear % 100 != 0)?29: 28);

if (testDay > 0 && testDay <= days)

return days;

}

cout << "今天Day" << testDay << "invalid set to day \n";

return 1;

}

void LeapYear::print () const

{

cout << iYear << '/' << iMonth << '/' << iDay;

}

void main()

{

LeapYear lyDay (1994, 2, 4);

// lyDay.setDay (4);

lyDay.print ();

cout << "年份" << lyDay.getYear () << endl;

cout << "月日" << lyDay.getDay () << endl;

}

II

***再续前情,此生不待 ---Skyala***

Skyala请您记住下面惊人的相似规律:

人(类)->父母(对象)->子女(继承、多重继承)->子孙(多态性)---哇,My God!多么完美的曲线!

面向对象程序设计总结:向对象发送消息。

可以减少函数传递过程中的参数

建立的类要有用,实用为准!

从此部分开始笔记中加入声明功能,并在每一定义部分后加入小程序(伪代码)用来讲解,方便多了。

*************************************声明*****************************

1. const对象和const函数

2. 友元(friend)类和友元函数

3. 静态(static)数据成员、静态数据函数及静态对象

4. 模块(template)类

5. 其他杂述(复合、包容器类、递取类......)

* 信息隐藏:对客户隐藏实现细节

类定义了抽象数据类型(ADT):表示了数据及对数据的操作

C++强调了数据的重要性

* char * temp = new char [stlen (fristname) + 1];

assert (temp != 0); //确认内存分配是否成功

6. 应用举例

a. 堆栈模块类 (TStack.cpp)

b. 遍历包容器类的递取类(Queue类)

c. List类

7.问题:

this指针不理解

为什么不能用const声明静态成员函数

************************************定义******************************

1. const对象和const函数

* const对象不能调用非const函数、不能修改const对象

const对象和const变量是不能赋值的,必须要初始化。在构造函数中可以用成员初始值进行初始化

* const成员函数不能调用非const成员函数、不能修改对象的数据成员

非const成员函数可重载为const成员函数

* 特例:当声明一个const对象时与构造函数和析构函数肯定会修改对象矛盾,此处这两个函数都不要声明关键字const,为了能正确初始化对象,允许这两个函数修改对象

* 切记:当一个类包括const对象时,必须给构造函数提供成员初始化值

class Time

{

Time(int = 0, int = 0);

void setTime(int = 0,int = 0,int = 0); //默认构造函数

int getHour() const {return hour;} //const成员函数

private:

int hour;

int time const; //const数据成员,要进行成员赋值初始化

}

Time::Time(int s, int m)

:time(m) //成员初始化值

{

hour = i;

time = m; //企图赋值,是错误的

//数据初始化

}

void main()

{

const Time T (12, 0, 0); // const对象不能赋值必须初始化

T.getHour(); // 正确,只有const成员函数才能访问const对象

T.setTime(); // 错误,非const函数

}

2.友元类和友元函数

友元函数是在类作用域外定义的,但它有权访问该类的私有成员和受保护成员

在类定义中,在函数原型或类前加入friend,它可放入类中任何地方,一般在类定义开始处

是一种“给予”关系,即B是A的友元,B可访问A中的数据成员及成员函数

class count

{

friend void setX(count & ,int); //声明友元类

public:

private:

int x; //私有数据成员

}

//看到此处了没有,没有用类的类作用域符号,它是类外的一个函数,区别处

void setX(count &c, int val)

{

c.x = val; //友元函数所以可以修改私有数据

}

void main()

{

count c;

setX(c, 8); //用友元函数设置x的值,此处也没用类作用域符,它是类作用外的一个函数

}

3.静态数据成员、函数及对象

* 类的对象通常都有该类的所有数据成员的单独拷贝,为了让对象共享一份拷贝引入静态(static)数据成员.可节省内存。好像全局变量但只有类作用域

* 公有的静态数据成员,可以用双目作用域符通过类名访问Time::count(最好在不存在对象时用),也可用类对象访问 T.count,静态成员函数只能用第二种方式

* 私有的和受保护的只能用公有静态成员函数访问。一个成员函数不要访问类的非静态成员时,声明为静态函数有利于节省内存

* 即使不存在类对象,静态数据成员、函数也存在并可使用。

public:

static int getCount();//静态函数

private:

static int count; //静态成员

int Time::getCount(return count;)

4.模板类(template )

模块类需要一种或多种类型参数,所以模板类也叫带参数的数据类型

声明:template <typename elemType>,模板类外的成员函数也都要以这个形式开头(多长了脑袋--Skyala)

template <typename elemType>

int Stack<elemType>::pop() {}

类名:Stack <elemType>,

实例化:Stack <float> floatStack ,stack为假设的一个模板类对象

多个参数:template <typename felemType,typename selemtype>

5.复合、包容器类、递取类及其他

* 复合: 一个类把另一个作为自己的成员,成员对象是在包括它们的对象之前建立的

成员对象不一定要提供成员初始化值的,其构造函数会自动调用,但如也没默认的构造函数,会出错

* 成员初始化值可避免对成员对象初始化两次(调用默认构造函数及用"set"函数)

Time::Time(int hour, int minute, int second)

:Minute (minute),

Second (second)

{}

6.应用举例:

编译环境:window2000 Vc6.0

a. Stack.cpp 堆栈类

#ifndef TSTACK_H

#define TSTACK_H

template<typename elemType>

class Stack

{

public:

Stack (int = 10); //构造函数,栈默认大小为10

~Stack (); //析构函数

int pop (elemType&); //入栈

int push (const elemType &); //出栈

int isEmpty () const {return _top == -1;} //栈空,返回-1

int isFull () const {return _top == _size - 1;} //栈滿,返回栈顶大小

private:

int _size; //堆栈能容纳元素的数目

int _top; //栈顶元素的数目

elemType * _stackPtr; //指向栈的指针

};

template<typename elemType>

Stack<elemType>::Stack (int s)

{

_size = s;

_top = -1; //空栈

_stackPtr = new elemType [_size];

}

template<typename elemType>

Stack<elemType>::~Stack ()

{ delete [] _stackPtr;}

//压入一元素,如成功返回1,失败返回0

template<typename elemType>

int Stack<elemType>::push (const elemType &item)

{

if (! isFull ())

{

_stackPtr [++_top] = item; //如栈没滿则栈顶赋值后加1

return 1; //成功

}

return 0; //入栈失败

}

//出栈

template<typename elemType>

int Stack<elemType>::pop (elemType &popValue)

{

if (! isEmpty ())

{

popValue = _stackPtr [_top--]; //如栈不为空则赋值后减1

return 1;

}

return 0;

}

#endif

#include <iostream.h>

#include <stdlib.h>

void main ()

{

Stack<int> floatStack (5); //模板实例化

int fS = 1;

cout << "Pushing \n";

while (floatStack.push (fS))

{

cout << fS << ' ';

fS += 1;

}

cout << "Full is:" << fS << '\n' << "Poping \n";

while (floatStack.pop (fS))

{

cout << fS << ' ';

}

cout << endl;

Stack<char> charStack (10);

char cS = 'a';

cout << "Pushing \n";

while (charStack.push (cS))

{

cout << cS << ' ';

cS += 1; //字符串可进行运算

}

cout << "Full is:" << cS << '\n' << "Poping \n";

while (charStack.pop (cS))

{

cout << cS << ' ';

}

cout << endl;

}

程序艺术--没了思想的程序永远不会打动人--天翼(Skyala)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有