对象和类
2009-8-1
1
.抽象和类
1.1
类型是什么
指定基本类型完成了
3
项工作:
ü
决定数据对象需要的内存数量。
ü
决定如何解释内存中的位(
long
和
float
在内存中占用的位数相同,但将他们装换为数值的方法不同)。
ü
决定可使用数据对象执行的操作或方法。
1.2
C++
中的类
共有成员函数是程序和对象的私有成员之间的桥梁,提供了对象和程序之间的接口。防止程序直接访问数据被称为数据隐藏。
类设计尽可能将公有接口与实现细节分开。公有接口表示设计的抽象组件。将实现细节放在一起并将它们与抽象分开被称为封装。数据隐藏(将数据放在类的私有部分中)是一种封装,将实现的细节隐藏在私有部分中。封装的另一个例子是,将类函数定义和类声明放在不同的文件中。
类和结构体
:
C++
对结构进行了扩展,使之具有与类相同的特性。它们之间唯一的区别是,结构的默认访问类型是
public
,而类为
private
。
C++
程序员通常使用类来实现描述,而把结构限制为只表示纯粹的数据对象或没有私有部分的类。
2009-8-6
晚
1.
内联方法
定义位于类声明中的函数都将自动成为内联函数。如果愿意,也可以在类声明之外定义成员函数,并使其成为内联函数,只需在类实现部分中定义函数时使用
inline
限定符即可:
Inline void
Stock::set_tot()
{
…..//
}
2.
方法使用哪个对象
所创建的每个新对象都有自己的存储空间,用于存储其内部变量和类成员;但同一个类的所有对象共享同一组方法,即每个方法只有一个副本。在
OOP
中,调用成员函数被称为发送消息,因此将同样的消息发送给
2
个不同的对象将调用同一个方法,但该方法被用于
2
个不同的对象。
3.
何时调用析构函数
何时调用析构函数是由编译器决定的,通常不该在代码中显示调用析构函数。
如果创建的对象是静态对象,其析构函数将在程序执行完代码块时自动被调用;如果对象是通过
new
创建的,则它将驻留在堆栈内存或自由存储区中,当使用
delete
才释放内存时,其析构函数将自动调用;最后,程序可以创建临时对象来完成特定的操作,此时,程序将在结束对该对象的使用时自动调用其析构函数。
4.
赋值与初始化的区别
Stock stock2 =
Stock(“Microsoft”, 2, 23.94);
stock1 = Stock(“Nifty
Foods”, 10, 3.22); //stock1
之前已存在
第一条语句是初始化,它创建有指定值的对象,可能会创建临时对象(也可能不会);第二条语句是赋值语句,像这样在赋值语句中使用构造函数总会导致在赋值前创建一个临时对象。
Tip
:
如果既可以通过初始化,也可以通过赋值来设置对象的值,则应该采用初始化的方式。通常这种方法的效率更高。
2009-8-7
上午
5. const
成员函数
const Stock land
= Stock(“Kludgehorn Propertites”);
land.show();
此时应该保证函数
show
不会修改调用对象,
C++
的解决办法是将
const
关键字放在函数的括号后面。也就是说
show
函数声明应该是这样的:
void show()
const;
同样,函数定义的开头应该是这样的:
void
Stock::show() const
{…//}
以这种方式声明和定义的函数被称为
const
成员函数。就像应尽可能将
const
引用和指针用作函数形参一样,只要方法不修改调用对象,就应该将其声明为
const
。
6.
构造函数和析构函数小结
接受一个参数的构造函数允许使用赋值句法来将对象初始化为一个值:
Classname object
= value
;
对于未被初始化的对象,程序将使用默认的构造函数来创建
:
Bozo bubi; //use
defalut
Bozo *pb = new
Bozo; //use default
1.3
对象数组
声明对象数组:
Stock s[5] =
{
Stock(“s1”,2,20.23),
Stock(“s2”,4,20.23),
Stock(“s3”,5,20.23),
Stock()
};
初始化对象数组的方案是,首先使用默认构造函数创建数组元素,然后花括号中的构造函数将创建临时对象,然后将临时对象的内容复制到相应的元素中。因此,要创建类对象数组,则这个类必须有默认构造函数。
1.4
类作用域
作用域为整个类的常量
class Stock
{
private:
const int Len = 30;
char company[Len];
…
};
这是不行的,因为声明类只是描述了对象的形式,没有真正创建对象。以下有两种方式可以达到目的:
class Stock
{
private:
enum{Len = 30};
char company[Len];
…….//
};
此时,声明的枚举并不会创建类数据成员。也就是说,所有对象中都不包含枚举。另外,
Len
只是一个符号名称(不需要枚举名),在作用域为整个类的代码中遇到它,编译器将用
30
来替代。
也可以像这样来实现同样的效果:
class Stock
{
private:
static const int Len = 30;
char company[Len];
……//
};
该常量将与其他静态变量存储在一起,而不是存储在对象中。因此,只有一个
Len
常量,它被所有
Stock
对象共享。只能使用这种技术声明值为整数或枚举的静态常量,而不能存储
double
常量。
相关示例代码:
//
SimpleList.h
#ifndef SIMPLELIST_H_
#define
SIMPLELIST_H_
const
int
sSize
=
20
;
struct
student
{
char
name[sSize];
int
age;
};
typedef
struct
student Item;
class
SimpleList
{
private
:
enum
{MAX
=
4
};
Item items[MAX];
int
count;
public
:
SimpleList();
bool
isempty()
const
;
bool
isfull()
const
;
int
getCount()
const
;
bool
additem(Item item);
void
transverse(
void
(
*
pf)(Item item));
const
Item
*
getTopAge()
const
;
Item
&
agedesc( Item
&
);
};
#endif
//
testlist.cpp
#include
"
SimpleList.h
"
SimpleList::SimpleList()
{
count
=
0
;
}
int
SimpleList::getCount()
const
{
return
count;
}
bool
SimpleList::isempty()
const
{
return
count
==
0
;
}
bool
SimpleList::isfull()
const
{
return
count
==
MAX;
}
bool
SimpleList::additem(Item item)
{
if
(
!
(isfull()))
{
items[count
++
]
=
item;
return
true
;
}
else
return
false
;
}
void
SimpleList::transverse(
void
(
*
pf)(Item item))
{
for
(
int
i
=
0
; i
<
count; i
++
)
(
*
pf)(items[i]);
}
const
Item
*
SimpleList::getTopAge()
const
{
const
Item
*
temp;
temp
=
&
items[
0
];
for
(
int
i
=
1
; i
<
count; i
++
)
if
(temp
->
age
<
items[i].age)
temp
=
&
items[i];
return
temp;
}
//
userlist.cpp
#include
<
iostream
>
#include
"
SimpleList.h
"
using
namespace
std;
void
showstu(Item);
void
showstu1(
const
Item
*
item);
int
main()
{
Item temp;
SimpleList s1;
cout
<<
"
Enter first student's name: \n
"
;
while
(cin.getline(temp.name, sSize)
&&
temp.name[
0
]
!=
'
\0
'
)
{
cout
<<
"
Enter student's age: \n
"
;
cin
>>
temp.age;
while
(cin.
get
()
!=
'
\n
'
)
continue
;
if
(
!
s1.additem(temp))
{
cout
<<
"
Add student fail! \n
"
;
break
;
}
cout
<<
"
count:
"
<<
s1.getCount()
<<
endl;
if
(s1.isfull())
{
cout
<<
"
student list is full! \n
"
;
break
;
}
cout
<<
"
Enter next student's name(EMPTY LINE TO STOP). \n
"
;
}
if
(s1.isempty())
cout
<<
"
No data to show! \n
"
;
else
{
cout
<<
"
Here is the student's info. \n
"
;
s1.transverse(showstu);
}
showstu1(s1.getTopAge());
return
0
;
}
void
showstu1(
const
Item
*
item)
{
cout
<<
"
name:
"
<<
item
->
name
<<
"
age:
"
<<
item
->
age
<<
endl;
}
void
showstu(Item item)
{
cout
<<
"
name:
"
<<
item.name
<<
"
age:
"
<<
item.age
<<
endl;
}