在面向对象的程序设计中,有经常接触类、对象等专业名词;到底什么是类、什么是对象呢?在程序又是怎样运用呢?类是面向对象程序设计的核心,它实际是一种新的数据类型,也是实现抽象类型的工具,因为类是通过抽象数据类型的方法来实现的一种数据类型。类是对某一类对象的抽象;而对象是某一种类的实例,因此,类和对象是密切相关的。没有脱离对象的类,也没有不依赖于类的对象。
什么是类
类是一种复杂的数据类型,它是将不同类型的数据和与这些数据相关的操作封装在一起的集合体。这有点像C语言中的结构,唯一不同的就是结构没有定义所说的“数据相关的操作”,“数据相关的操作”就是我们平常经常看到的“方法”,因此,类具有更高的抽象性,类中的数据具有隐藏性,类还具有封装性。
类的结构(也即类的组成)是用来确定一类对象的行为的,而这些行为是通过类的内部数据结构和相关的操作来确定的。这些行为是通过一种操作接口来描述的(也即平时我们所看到的类的成员函数),使用者只关心的是接口的功能(也就是我们只关心类的各个成员函数的功能),对它是如何实现的并不感兴趣。而操作接口又被称为这类对象向其他对象所提供的服务。
类的定义格式
类的定义格式一般地分为说明部分和实现部分。说明部分是用来说明该类中的成员,包含数据成员的说明和成员函数的说明。成员函数是用来对数据成员进行操作的,又称为“方法”。实现部分是用来对成员函数的定义。概括说来,说明部分将告诉使用者“干什么”,而实现部分是告诉使用者“怎么干”。
类的一般定义格式如下:
class <类名>
{
public:
<成员函数或数据成员的说明>
private:
<数据成员或成员函数的说明>
};
<各个成员函数的实现>
下面简单地对上面的格式进行说明:class是定义类的关键字,<类名>是种标识符,通常用T字母开始的字符串作为类名。一对花括号内是类的说明部分(包括前面的类头)说明该类的成员。类的成员包含数据成员和成员函数两部分。从访问权限上来分,类的成员又分为:公有的(public)、私有的(private)和保护的(protected)三类。公有的成员用public来说明,公有部分往往是一些操作(即成员函数),它是提供给用户的接口功能。这部分成员可以在程序中引用。私有的成员用private来说明,私有部分通常是一些数据成员,这些成员是用来描述该类中的对象的属性的,用户是无法访问它们的,只有成员函数或经特殊说明的函数才可以引用它们,它们是被用来隐藏的部分。保护类(protected)将在以后介绍。
关键字public,private和protected被称为访问权限修饰符或访问控制修饰符。它们在类体内(即一对花括号内)出现的先后顺序无关,并且允许多次出现,用它们来说明类成员的访问权限。
其中,<各个成员函数的实现>是类定义中的实现部分,这部分包含所有在类体内说明的函数的定义。如果一个成员函数的类体内定义了,实现部分将不出现。如果所有的成员函数都在类体内定义,则实现部分可以省略。
下面给出一个日期类定义的例子:
class TDate
{
public:
void SetDate(int y, int m, int d);
int IsLeapYear();
void Print();
private:
int year, month, day;
};
//类的实现部分
void TDate::SetDate(int y, int m, int d)
{
year = y;
month = m;
day = d;
}
int TDate::IsLeapYear()
{
return(year%4==0 && year%100!=0) || (year%400==0);
}
void TDate::Print();
{
cout<<year<<"."<<month<<"."<<day<<endl;< font="" style="font-family: Arial; font-size: 14px; line-height: 24px; ">
}
这里出现的作用域运算符::是用来标识某个成员函数是属于哪个类的。
该类的定义还可以如下所示:
class TDate
{
public:
void SetDate(int y, int m, int d)
{year=y; month=m; day=d;}
int IsLeapYear()
{return(year%4==0 && year%100!=0) || (year%400==0);}
void Print()
{cout<<year<<"."<<month<<"."<<day<<endl;}< font="">
private:
int yeay, month, day;
}
这样对成员函数的实现(即函数的定义)都写在了类体内,因此类的实现部分被省略了。如果成员函数定义在类体外,则在函数头的前面要加上该函数所属类的标识,这时使用作用域运算符::。
定义类时应注意的事项
1、在类体中不允许对所定义的数据成员进行初始化。
2、类中的数据成员的类型可以是任意的,包含整型、浮点型、字符型、数组、指针和引用等。也可以是对象。另一个类的对象,可以作该类的成员,但是自身类的对象是不可以的,而自身类的指针或引用又是可以的。当一个类的对象用为这个类的成员时,如果另一个类的的定义在后,需要提前说明。
3、一般地,在类体内先说明公有成员,它们是用户所关心的,后说明私有成员,它们是用户不感兴趣的。在说明数据成员时,一般按数据成员的类型大小,由小至大说明,这样可提高时空利用率。
4、经常习惯地将类定义的说明部分或者整个定义部分(包含实现部分)放到一个头文件中。
对于 public类成员来说,他们是公有的可以被外部程序访问,对于private类成员来说他们是私有的,只能有类的函数所使用,不能被外部程序访问。
/**首先定义类*/
class CMeter
{
...
private:
int m_nPos=10;//不能对类的成员初始化操作 出错
void Sum (int iNum1,int iNum2);
...
}; //注意定义类末尾的分号
/**定义类的对象*/
格式 <类名><对象表>
例子 CMeter My_Meter, *pMeter, Meter[N];
下面是随便写的一段代码希望能给大家帮助 里面的错误谁能找出来啊???有什么更好的方法解决么?
// test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "stdafx.h"
#include <windows.h>
#include <math.h>
//#include <iostream.h>
#include <iostream>
using namespace std;
void tool_N_to_BCD(long i);
class CmyClass
{
public: //公有类
double dNnum;
long lP;
long a;
long b;
long c;
void Fun_xy();
int Fun_sun_public(long a,long b ,long c);//类的公有成员a b c 可以被访问
~CmyClass(){} //析构函数
private: //私有类
long sum=(a+b)*c
int Fun_sun(long a,long b ,long c);
void Fun_sun_public(long a,long b ,long sum);//私有成员函数可以访问公有成员和私有成员!
};
void CmyClass::Fun_xy()
{
cout << "请输入函数Ax^2+Bx+C=y的a b c"<< endl;
cin >>a>>b>>c;
cout <<a<<"x^2+"<<b<<"x+"<<c<<"+0"<< endl;
double x1=0,tmp=b*b-4*a*c;
cout <<"△="<<tmp<<endl;
if(tmp > 0 || tmp == 0)
{
x1=(-b-sqrt(tmp))/(2*a);
cout <<"x1="<<x1<< endl;
cout <<"x2="<<(-b+sqrt(tmp)/(2*a))<< endl;
}
else
{cout<<"没有交点"<<endl;
cout <<"Xi1="<<-b/(2*a)<<"+"<<"sqrt("<<tmp<<"*i)/"<<2*a<<endl;
cout <<"Xi2="<<-b/(2*a)<<"-"<<"sqrt("<<tmp<<"*i)/"<<2*a<<endl;
}
}
int CmyClass:: Fun_sun_public(long a,long b ,long c)
{
Fun_sun(a, b , c);
return 0;
}
int CmyClass::Fun_sun(long a,long b ,long c) //类成员公有函数
{
CmyClass::Fun_xy();
cout <<a<<"x^2+"<<b<<"x+"<<c<<"=0"<< endl;
Fun_xy();
cout <<a<<"x^2+"<<b<<"x+"<<c<<"=0"<< endl;
cout <<"a+b+c="<<a+b+c<< endl;
return 0;
}
CmyClass character[4]; //定义class CmyClass 类的4个数组对象
int main()
{
std::cout << "这是第一个程序" << endl;//限定输出原因是 定义了 #include <iostream> using namespace std; 如果定义#include <iostream.h>则不需要限定
long i=0;
int iNum1=0, iNum2=0;
while(1)
{
cout << "请输入10进制i值" << endl;
std::cin >>i;
// if( isdigit(i)!=0 )//判断是否输入的是数字字符 注意是字符不是字符串
// continue;
cout << "请输入2个要求和的整数:"<< endl;
cin >>iNum1;
cin >>iNum2;
/*
cout << iNum1<<endl;
cout << "+"<<endl;
cout << iNum2<<endl;
cout << "=" <<endl;
cout << iNum1+iNum2 <<endl;
*/
cout << "i=" << i<<endl;
std::cout << iNum1<< "+"<<iNum2<< "=" << iNum1+iNum2 <<endl;
cout <<"十进制\t"<< "i=" << i<<endl;
cout <<"hex\t"<< "i=" <<hex<< i<<endl;
cout <<"Oct\t"<< "i=" <<oct<< i<<endl;
cout <<"Dec\t"<< "i=" <<dec<< i<<endl;
tool_N_to_BCD(i);
cout <<iNum1<<"\t"<<iNum2<<"\t"<<i<<endl;//< font="" style="font-family: Arial; font-size: 14px; line-height: 24px; ">
cout <<"原来class CmyClass 的 character.lP;"<<character[0].lP<<endl;
cout <<"请输入class CmyClass 的 character.lP;"<<endl;
cin >>character[0].lP;
cout <<"输入class CmyClass 的 character.lP;"<<endl;
for(int i=0;i<2;i++)
{
character[i].Fun_xy();
// character[0].Fun_sun(0,0,0);//类私有函数无法访问
character[i].Fun_sun_public(0,1,22);
}
}
return 0;
}
void tool_N_to_BCD(long i) //十进制转2进制
{
/*十进制整数转换为二进制整数采用"除2取余,逆序排列"法。具体做法是:用2整除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,如此进行,直到商为0时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。
十进制整数转二进制**/
/*789=1100010101
789/2=394 余1 第10位
394/2=197 余0 第9位
197/2=98 余1 第8位
98/2=49 余0 第7位
49/2=24 余1 第6位
24/2=12 余0 第5位
12/2=6 余0 第4位
6/2=3 余0 第3位
3/2=1 余1 第2位
1/2得0 余1 第1位*/
int ilen=0;
int j=0,tmp=0;
double *p=0;
char *q=0;
char cTemp[20]="";
/*
itoa(i, cTemp, 2);//2进制输出
cout <<cTemp<<endl;
*/
if(i%1000 > 0)
{ilen=4;}
else if(i%100 > 0)
{ilen=3;}
else if(i%10 > 0)
{ilen=2;}
else{ilen=1;}
p=new double(8);
while(i)
{
if( i%10>0 || i%10 == 0)
{
tmp=i%2;
*p*=10;
*p+=tmp;
i/=2;
j++;
}
}
cout <<*p<<endl;
//逆序输出既为2进制
//逆序输出
int pt=(int)*p;
sprintf(cTemp, "%d", pt);
for( i=j;i > 0; i--)
{
std::cout<<cTemp[i];
}
cout<<"\n"<<endl;
delete p;
}