C++中, 除了int, doubel, char 等等built-in 的datatypes, 还可以根据实际的需要, 自己定义所需的数据类型。这里介绍两种自定义的数据类型, 一个是类(class), 另一种是struct(结构体)。
C++拥有class(类)的概念,而C语言没有,这可能是C++区别于C语言最大的不同之处吧。类属于用户自定义的数据类型。其用法和int, double等的数据类型的用法是基本相似的。我们可以用一个class 去声明一个对象(object),就相当于我们用int 声明一个整型变量一样。对象(objects)既有成员数据,又有成员函数。这里所说的objects适合OOP(object-oriented programing,一种很有名的,功能强大的编程范式)中的面向对像是一样的。
在介绍class 的概念之间,我们首先介绍一个carry-over from the C 的概念,结构体(structures)。这也是一个user defined的datatype。
结构体的一个最大的特点就是将a collection of data items of diverse types。注意虽然structures在C++ 中可以拥有成员函数(member function),但是我们在这里忽略这一点(为了区分),说结构体可以被看成一个只有成员变量的对象。
结构体允许内部的各个成员变量可以属于不同的类型,这个特点尤为重要,因为这使得我们可以将相关联的变量(例如一个类的属性值),尽管变量可能属于不同的类型,我我们却可以将其封装为一个结构体。例如一个银行存款本(certificate of deposit),具有的属性我the account balance, the interest rate, the term(the number of months until maturity). 如下:
struct CDAccount {
double balance;
double interestRate;
int term; //months until maturity
}; // 注意这个分好“;”也属于结构体定义的一部分, 必须带上, 这是容易出错的
再比如, 一个MIT的sudent 具有两个属性, 一个是name, 一个是学号, 我们可以如下定义一个结构体(user-defined datatype)
struct MITStudent {
char* name;
int studentID;
};
下面给出一个关于struct的例子:
#include
using namespace std;
struct CDAccount {
double balance;
double interestRate;
int term; //months until maturity
}; // 不要忘了分号, struct的一部分
void getData(CDAccount & theAccount); //passing by reference
//Postcondition: theAccount.balance, theAccount.interestRate, and
//theAccount.term have been given values that the user entered at the
//keyboard
int main() {
CDAccount account;
getData(account);
double rateFraction, interest;
rateFraction = account.interestRate/100.0;
interest = account.balance * (rateFraction * (account.term/12.0)); //年利率, 6个月相当于乘以0.5
account.balance = account.balance + interest;
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
cout << "When your CD matures in "
<< account.term <<" months, \n"
<< "it will have a balance of $"
<< account.balance << endl;
return 0;
}
// Uses iostream
void getData(CDAccount& theAccount) {
cout << "Enter account balance: $";
cin >> theAccount.balance;
cout << endl;
cout << "Enter interest rate: ";
cin >> theAccount.interestRate;
cout << endl;
cout << "Enter the number of months until maturity: ";
cin >> theAccount.term;
cout << endl;
}
运行结果如下:
上面测试的时候, 年利率为为0.1%
NOTE: (1)struct 结构体类型定义一般放在所有函数(包括main函数)之外, 这样, 结构体类型就是一个全局变量, 所有的函数都可以使用这个类型。
(2)stuct 这个用户自定义的类型里面的成员变量的access modifier 默认为public, 例如上个例子中的balance 等成员变量, 正因为如此, 我们的该结构体对象可以直接以dot operator 的方式存取自己的成员变量。例如上例中的theAccount.balance等等。
同一个程序中, 不同的结构体可以使用相同的成员函数名:
struct FertilizerStock {
double quantity; //type doubel
double nitrogenContent;
};
struct CropField {
int quantity; // reusing member name, okay! type int
double size;
};
上述同名字的出现是没有问题的。例如, 我们利用二者什么两个结构体变量:
FertilizerStock superGrow;
CropField apples;
因为superGrow的quantity变量是存储在superGrow.quantity, apples 的quantity 存储在成员变量apples.quantity中的, the dot operator and the structure variable specify which quantity is meant ineach instance。
结构体变量之间的赋值(和int , char 等变量是一致的)。
例如如果apples 和 oranges均是由结构体数据类型定义的结构体变量, 那么下面的语句时合法的:
apples = oranges;
上述语句等价于:
apples.quantity = oranges.quantity;
apples.size = oranges.size;
结构体类型可以作为函数的参数, 函数也可以返回一份结构体变量。 如上面的例子, 函数将现在利率变为原来的两倍如下:
CDAccount doubleInterest(CDAccount oldAccount) { // a function takes structure as an argument and returns an argument
CDAccount temp; temp = oldAccount;
temp.interest.Rate = 2 * oldAccount.interestRate;
return temp;
}
下面在举一个上面的程序改进后的例子:
#include
using namespace std;
struct Date {
int month;
int day;
int year;
};
// improved structure for a bank certificate of deposit
struct CDAccountNew {
double initialBalance;
double interestRate;
int term; //months until maturity
Date maturity; //date when CD matures
double balanceAtMaturity;
};
void getCDData(CDAccountNew & theAccount); //passing by reference
//Postcondition: theAccount.initialBalance, theAccount.interestRate, and
//theAccount.term and the Account.maturity have been given values that
//the user entered at the
//keyboard
void getDate(Date& theDate);
//Postcondition: theDate.month, theDate.day, theDate.year have
//been given values that the user entered at the keyboard.
int main() {
CDAccountNew account;
cout << "Enter account data on the day account was opened: \n";
getCDData(account);
double rateFraction, interest;
rateFraction = account.interestRate/100.0;
interest = account.initialBalance * (rateFraction * (account.term/12.0)); //年利率, 6个月相当于乘以0.5
account.balanceAtMaturity = account.initialBalance + interest;
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
cout << "When your CD matures on "
<< account.maturity.month << "-" << account.maturity.day
<< "-" << account.maturity.year << endl
<< "it will have a balance of $"
<< account.balanceAtMaturity << endl;
return 0;
}
// Uses iostream
void getCDData(CDAccountNew& theAccount) {
cout << "Enter account balance: $";
cin >> theAccount.initialBalance;
cout << endl;
cout << "Enter account interest rate: ";
cin >> theAccount.interestRate;
cout << endl;
cout << "Enter the number of months until maturity: ";
cin >> theAccount.term;
cout << endl;
cout << "Enter the maturity date: ";
getDate(theAccount.maturity);
}
void getDate(Date& theDate) {
cout << endl;
cout << "Enter month: " ;
cin >> theDate.month;
cout << endl;
cout << "Enter day: ";
cin >> theDate.day;
cout << endl;
cout << "Enter year: ";
cin >> theDate.year;
}
运行结果为:
NOTE: 对structures的初始化, 我们可以在声明结构体类型变量的同时进行初始化:
例如:
struct Date {
int month;
int day;
int year;
};
然后我们利用上面定义的结构体数据类型声明变量:
Date dueDate = {12, 31, 2003};
按照{} 内数字的顺序给对应的结构体成员变量赋值。 对于未初始化的结构体的成员变量, 默认赋值为0.
例如:
Date dueDate = {12, 31}; // dueDate.month = 12, dueDate.day = 31; dueDate.year = 0