一、结构体
1、结构体定义
struct BOOK
{
char Title[80];
char Author[80];
char Publisher[80];
int Year;
};
2、结构体变量声明
BOOK Novel;
3、初始化结构体
BOOK Novel=
{
"Paneless Programming",
"I.C.Fingers",
"Gutter press",
1981
}; 这些初始化值位于大括号内,
相互之间以逗号分开,这种方式
与为数组成员定义初值的方式完全相同。
4、访问机构成员
Novel.Year=1988;
5、使用指针处理结构
BOOk* pBook=NULL;
pBook=&Novel;
RECT aRect={0,0,100,100};
RECT* pRect=&aRect;
(*pRect).Top+=10;
pRect->Top+=10;
6、包含自己指针的结构
struct ListElement
{
BOOK aBook;
ListElement* pNext;
};
二、类
1、类的定义
class CBox
{
private: 类的私有成员。
double m_Length;
double m_Width;
double m_height;
char *pmessage;
friend double BoxSurface(CBox aBox); 类的友元函数定义。
public: 类的公有成员。
static int objectCount; 类的静态数据成员。 所有的类的对
象都共享一个此成员。
int CBox::objectCount=0; 采用此方
法初始化此成员。
可以通过CBox::objectCount
或者对象.objectCount 访问此变量。
既是没有任何对象存储,类的static
成员也可能存在。
静态数据成员在程序启动时候自动创建,
并被初始化为0. 如果我们希望
静态数据成员最初是非零值时,
才需要我们初始化它们。
static void Afunction(int n); 静态成员函数的定义:既是本类的
任何对象不存在,也可以调用静态成员函数。
这种情况下,静态成员函数只能使用静态数据成员。
反之如果对象存在了。就可以访问对象的数据成员了。
例如:aBox.Afunction(10);
或者 CBox::Afunction(10);
double volume(void);
double GetLength(void);
double GetWidth(void) const; 定义为const函数,其作用是使该函数中的this指针为const。
我们不能在该函数的定义内赋值语句左边些上类的数据成员。
const成员函数不能调用同类的非const成员函数。
CBox(){}; 默认构造函数,如果不给类定义任何构造
函数则编译器定义默认构造函数,反之
如果给定义了构造函数,那么编译器不
在给类定义默认构造函数。如果需要则需要人工定义。
CBox(double lv,double bv,double hv); 构造函数的定义
CBox(double lv=1.0,double bv=1.0,double hv=1.0); 在类定义中指定默认的形参值。
如果有此函数 则需要去掉 默认
构造函数。
CBox(const char* text="Default message");
CBox(double lv=1.0,double bv=1.0,double hv=1.0):
m_Length(lv),m_Width(bv),m_Height(hv) 在构造函数中使用初始化列表。
CBox(const CBox& initB); 复制构造函数的定义。 复制构造函数是通过
用同类的现有对象进行初始化,从而创建新
对象的构造函数,因此需要接受同类的对象作
为实参。
~CBox(); 析构函数用于销毁不再需要或者不再有
效的对象.
void ShowIt() const;
bool operator>(const CBox& aBox) const; 重载>运算符
};
double CBox::Volume()
{
return m_length*m_Width*m_Height;
}
inline double CBox::GetLength() 内联函数,相当于把函数体复制到调用的地方。
{ 访问类的私有成员。
return m_Length;
}
CBox::CBox(double lv,double bv,double hv) 构造函数的实现
{
m_Length=lv;
m_Width=bv;
m_Height=hv;
}
CBox(double lv=1.0,double bv=1.0,double hv=1.0) 默认形参值的函数实现部分。
{
m_Length=lv;
m_Width=bv;
m_Height=hv;
}
double BoxSurface(CBox aBox) 此函数虽然不是类成员的函数,
{ 但是确能访问类的所有成员。
return 2.0*(aBox.m_Length*aBox.m_Width+ 可以在类定义中包括友元函数的原型,
aBox.m_length*aBox.m_Height+ 可以可以包括真个函数定义。在类定
aBox.m_Height*aBox.m_Width); 义内定义的类的友元函数默认也是内联函数。
} 友元函数不是类的成员。因此访问特性不适
用它们。这些函数只是拥有特殊权限的普通
全局函数。
double CBox::GetWidth(void) const const成员函数的实现。
{
return this->m_Width;
}
CBox::CBox(const CBox& initB) 复制构造函数的实现。
{
m_Length=initB.m_Length;
m_Width=initB.m_Width;
m_Height=initB.m_Height;
pmessage= new char[strlen(initB.pmessage)+1]; 因为的对象的成员pmessage是new动态分配的,
strcpy(pmessage,initB.pmessage); 在复制构造中,复制只能复制到对象的地址,
如果一个对象释放,那么另外一个对象的成
} 员也被释放,为了避免这个问题,需要手动复制
成员对象内存的实际数据.
CBox::~CBox() 一般我们不需要显式调用析构函数,当某个
{ 对象无效时,编译器将自动安排调用给类
cout<<"Destructor called."<<endl; 的析构函数.系统函数,释放构造函数分
delete[] pmessage; 配的内存.
}
CBox::CBox(const char* text="Default message") 构造函数
{
pmessage= new char(strlen(text)+1);
strcpy(pmessage,text);
}
void CBox::ShowIt() const
{
cout<<endl<<pmessage;
}
void DisplayMessage(CBox,localBox) 这样致命的错误是,形参是按值传递,localBox
{ 是调用了复制构造函数形成的原本对象的副本.
cout<<endl<<"The message is:"<<localMsg.ShowIt();如果这个函数调用完,localBox释放,那么就
return; 随即释放了实参的成员.如果在调用实参的,
} 成员变量内容,则是一个随即的数据,如果以后
在把此对象作为其他函数的实参,那么这个对象
成员变量所指的对象都是一个随即的数据.
bool CBox::operator>(const CBox& aBox) const >运算符重载的实现
{
return this->Volume()>aBox.Volume();
}
2、类对象使用
CBox boxes[5]; 声明对象数组,将调用CBox的默认构造函数。
CBox MyBox; 定义CBox变量,将调用CBox的默认构造函数。
CBox MyBox1(2,3,4); 定义CBox变量,将调用CBox的自定义构造函数。
MyBox.Volume(); 对象访问成员函数。
BoxSurface(MyBox1); 访问友元函数,跟普通的函数调用是一样的。
MyBox.GetWidth(); 访问对象的const成员函数。
CBox Box=MyBox1; 用对象MyBox1初始化Box,调用的是对象的
复制构造函数。
3、类对象的指针很引用
CBox* pBox=0; 声明对象指针。
pBox=&cigar; 给对象指针赋值。
count<<pBox->Volume(); 通过指针访问对象的成员函数。
CBox& rcigar=cigar; 类引用的定义。
cout<<rcigar.Volume(); 通过引用访问对象成员函数。
CBox* pbox= new CBox("A cat can look at a queen."); 有指针动态初始化对象,
pbox->ShowIt(); 指针调用对象的方法.
delete pbox; 删除对象指针,只有这个对象指针是new
分配的时候,才需要.
三、联合
1、联合的定义
union shareLD dval和lavl公有一块内存,如果dval给赋值,
{ 那么就覆盖了lval。
double dval;
long lval;
};
2、联合变量的声明
shareLD myUnion; 或者
union shareLD
{
double dval;
long lval;
}myUnion;
3、联合变量使用
myUnion.lval=100;
4、联合的初始化 联合占用的内存大小取决于最大的成员。
union shareDLF |-------------8个字节-----------|
{ |___|___|___|___|___|___|___|___|
double dval; |--lavl4个字节--|
long lval; | |
float fval; |--favl4个字节--|
}uinst={1.5}; | |
|------------dval8个字节---------|
当声明实例时,我们只能初始化联合的第
一个成员。
5、匿名联合
union
{
char* pval;
double dval;
long lval;
}
四、重载运算符
运算符重载功能不允许我们使用新的运算符,也不允许我们改变运算符的优先级。
不能重载的运算符: ?:, ., sizeof, .*,::
class Length
{
private:
double len;
public:
Length& operator++(); 前加运算符
const length operator++(int); 后加运算符
Length& operator--(); 前减运算符
const Length operator--(int); 后减运算符
}
Length& Length::operator++() 前加运算符的实现
{
++(this->len);
return *this;
}
const Length& Length::operator++(int) 后加运算符的实现,返回const,
{ 以防止类似data++这样的表达式被编译。
Length length=*this;
++*this;
return length;
}
五、类模板
1、定义类模板
template<class T> 任何用来根据模板实例化某个类的类类型,
都必须已经定义过模板的成员函数
class CSamples 处理本类对象时要用到的所有运算符。
{
public:
CSamples(const T values[],int count); 构造函数在外部实现
CSamples(const T& value)
{
m_Values[0]=value;
m_Free=1;
}
CSamples(){m_Free=0}
bool Add(const T& value)
{
bool OK=m_Free<100;
if(OK)
m_Values[m_Free++]=value;
return OK:
}
T Max() const; 在模板类外实现的函数
private:
T m_Values[100];
int m_Free;
};
template<class T> 作用域解析运算符之前只能使用附带形参
名称T的模板名。这是必须的。
T CSamples<T>::Max() const 形参识别出根据该模板生成的函数属于
{ 那个类非常重要。类模板的类型是CSamples<T>,
T theMax=m_Free?m_values[0]:0; 其中T是我们创建类模板实例时指定的类型。
for(int i=1;i<m_Free;i++) CSamples<T>::前面的T是Max函数的返回值。
if(m_Values[i]>theMax)
theMax=m_Values[i];
return theMax;
}
template<class T>
CSamples<T>::CSamples(const T values[],int count) 在外部实现的构造函数。
{ 注意没有返回值
m_Free=count<100?count:100;
for(int i=0;i<m_Free;i++)
m_Values[i]=values[i];
}
2、根据类模板创建对象
CSamples<double> myData(10.00); 为了声明一个CSamples<>对象来处理double
类型的样本。
转载于:https://blog.51cto.com/rosehacker/448695