C++简单程序典型案例
【案例2-1】设计一个编写仅包含C++程序基本构成元素的程序
/* //注释行开始
This is the first C++ program.
Designed by zrf
*/ //注释行结束
#include <iostream> //包含头文件
using namespace std; //打开命名空间std
// This is the main function //单行注释语句
int main(void) //主函数,程序入口
{ //块作用域开始
int age; //声明一个变量
age= 20; //赋值语句
cout<<"The age is:\n"; //输出一个字符串
cout<<age<<endl; //输出变量中的值
return 0; //主函数返回0
} //块作用域结束
【案例2-2】计算圆的周长和面积——C++语言中常量、变量
#include <iostream>
using namespace std;
int main()
{ const float PI=3.1415926; //float 型常量
float r=2.0; //用float 型常量初始化变量
cout<<"r="<<r<<endl; //输出圆的半径
float length; //float型变量声明
length=2*PI*r; //计算圆的周长
cout<<"Length="<<length<<endl; //输出圆的周长
float area=PI*r*r; //计算圆的面积
cout<<"Area="<<area<<endl; //输出圆的面积
return 0;
}
【案例2-3】整数的简单运算——除法、求余运算法和增量减量运算符
#include <iostream>
using namespace std;
int main()
{ int x, y;
x = 10; y = 3;
cout << x << " / " << y << " is " << x / y //整数的除法操作
<<" with x % y is " << x % y << endl; //整数的取余操作
x ++; --y ; //使用增量减量运算符
cout << x << " / " << y << " is " << x / y << "\n" //整数的除法操作
<< x << " % " << y << " is " << x % y<<endl; //整数的取余操作
return 0;
}
【案例2-4】多重计数器——前置和后置自增运算符
#include<iostream>
using namespace std;
int main()
{ int iCount=1; iCount=(iCount++)+(iCount++)+(iCount++); //后置++
cout<<"The first iCount="<<iCount<<endl;
iCount=1; iCount=(++iCount)+(++iCount)+(++iCount); //前置++
cout<<"The second iCount="<<iCount<<endl;
iCount=1; iCount=-iCount++; //后置++
cout<<"The third iCount="<<iCount<<endl;
iCount=1; iCount=-++iCount; //前置++
cout<<"The fourth iCount="<<iCount<<endl;
return 0;
}
【案例2-5】对整数“10”和“20”进行位运算——位运算的应用
#include <iostream>
using namespace std;
int main()
{ cout << "20&10=" << (20&10) << endl; //按位与运算
cout << "20^10=" << (20^10) << endl; //按位异或运算
cout << "20|10=" << (20|10) << endl; //按位或运算
cout << "~20=" <<(~20) << endl; //按位取反运算
cout << "20<<3=" << (20<<3) << endl; //左移位运算
cout << "-20<<3=" << (-20<<3) << endl; //左移位运算
cout << "20>>3=" << (20>>3) << endl; //右移位运算
cout << "-20>>3=" << (-20>>3) << endl; //右移位运算
return 0;
}
【案例2-6】实现逻辑“异或”运算——逻辑运算应用
#include <iostream>
using namespace std;
int main()
{ bool p, q;
p = true; q = true;
cout <<p <<" XOR "<<q<<" is "<<( (p || q) && !(p && q) )<< "\n"; //输出异或结果
p = false; q = true;
cout <<p<<" XOR "<<q<< " is "<<( (p || q) && !(p && q) )<< "\n"; //输出异或结果
p = true; q = false;
cout <<p<<" XOR "<<q<<" is "<<( (p || q) && !(p && q) )<< "\n"; //输出异或结果
p = false; q = false;
cout <<p<<" XOR "<<q<<" is "<<( (p || q) && !(p && q) )<< "\n"; //输出异或结果
return 0;
}
【案例2-7】高效筛选器——用条件运算符“?”构建条件表达式
#include<iostream>
using namespace std;
int main()
{ int iNum1=1,iNum2,iMax;
cout<<"Please input two integers:\n";
cin>>iNum1>>iNum2;
iMax = iNum1>iNum2 ? iNum1 : iNum2; //使用条件运算符构建条件表达式
cout<<"The max integer is: "<<iMax<<endl;
return 0;
}
【案例2-8】“多计算与单提取”功能的实现——逗号表达式
#include<iostream>
using namespace std;
int main()
{ int Val1, Val2, Val3, Left, Midd, Righ;
Left = 10; Midd = 20; Righ = 30;
Val1 = (Left++, --Midd, Righ++); //使用逗号表达式
Val2 = (Righ++, Left++, --Midd); //使用逗号表达式
Val3 = ( --Midd, Righ++,Left++); //使用逗号表达式
cout <<"Val1=\t"<<Val1 <<"\nVal2=\t"<<Val2 <<"\nVal3=\t"<<Val3<<endl;
return 0;
}
【案例2-9】高效的算术运算符——复合赋值运算符
#include <iostream>
using namespace std;
int main()
{ int n=20; cout << "n = " << n << endl;
n += 8; cout << "After n += 8, n = " << n << endl; //使用复合的赋值运算符+=
n -= 6; cout << "After n -= 6, n = " << n << endl; //使用复合的赋值运算符-=
n *= 1; cout << "After n *= 1, n = " << n << endl; //使用复合的赋值运算符*=
n /= 4; cout << "After n /= 4, n = " << n << endl; //使用复合的赋值运算符/=
n %= 3; cout << "After n %= 3, n = " << n << endl; //使用复合的赋值运算符%=
return 0;
}
【案例2-10】计算不同数据类型的存储容量——sizeof运算符
#include <iostream>
using namespace std ;
int main()
{ cout << "The size of an int is:\t\t" << sizeof(int) << " bytes.\n";
cout << "The size of a short int is:\t" << sizeof(short) << " bytes.\n";
cout << "The size of a long int is:\t" << sizeof(long) << " bytes.\n";
cout << "The size of a char is:\t\t" << sizeof(char) << " bytes.\n";
cout << "The size of a wchar_t is:\t" << sizeof(wchar_t) << " bytes.\n";
cout << "The size of a float is:\t\t" << sizeof(float) << " bytes.\n";
cout << "The size of a double is:\t" << sizeof(double) << " bytes.\n";
return 0;
}
【案例2-11】巧妙获取整数部分——double和int数据类型的转换
#include <iostream>
using namespace std;
int main()
{ int nn=10,mm;
double xx=4.741,yy;
cout<<"nn*xx="<<nn*xx<<endl; //表达式类型转换
mm=xx; yy=nn; //赋值类型转换
cout<<"mm="<<mm<<endl <<"yy="<<yy<<endl;
cout<<"int(xx)="<<int(xx)<<endl <<"(int)xx="<<(int)xx<<endl; //强制类型转换
cout<<"int(1.412+xx)="<<int(1.412+xx)<<endl; //强制类型转换
cout<<"(int)1.412+xx="<<(int)1.412+xx<<endl; //强制类型转换
return 0;
}
【案例2-12】将分数转换为小数——强制类型转换
#include <iostream>
using namespace std;
int main()
{ for( int i=1; i <= 5; ++i )
cout << i << "/ 3 is: " << (float) i / 3 << endl; //强制类型转换
return 0;
}
【案例2-13】安全的除法计算器
#include <iostream>
using namespace std;
int main()
{ int a, b;
cout << "Enter numerator: "; cin >> a;
cout << "Enter denominator: "; cin >> b;
if(b) cout << "Divide Result is: " << a / b << '\n'; //排除除数为零的情况
else cout << "Divide by zero!\n";
return 0;
}
【案例2-14】猜数游戏——嵌套的if条件语句
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{ int MagNum, GueNum;
MagNum = rand(); //产生随机数
cout << "Enter the Guess number: "; cin >> GueNum;
if (GueNum == MagNum)
{ //if语句块起始位置
cout << "* It is Right *\n"<< MagNum << " is the Magess number.\n";
} //if语句块结束位置
else
{ // else语句块起始位置
cout << "Sorry, you're wrong."<<endl;
if(GueNum > MagNum)
cout <<"Guessed number is too high.\n";
else
cout << "Guessed number is too low.\n";
} //else语句块结束位置
return 0;
}
【案例2-15】根据输入月份输出从年初到本月底的天数——不带break的switch
#include <iostream>
using namespace std;
int main()
{ int year,month,days=0;
cout<<"Input year and month:"; cin>>year>>month;
switch (month) //每个case分支均没有break语句
{ case 12: days +=31;
case 11: days +=30;
case 10: days +=31;
case 9: days +=30;
case 8: days +=31;
case 7: days +=31;
case 6: days +=30;
case 5: days +=31;
case 4: days +=30;
case 3: days +=31;
case 2: //判断是否为闰年
if (year % 4==0 && year % 100!=0 || year %400==0)
days +=29;
else
days +=28;
case 1: days +=31;
}
if (days==0) cout<< "Wrong month"<<endl;
else cout << "Total days is:" <<days<< endl;
return 0;
}
【案例2-16】计算数的阶乘——do-while循环语句
#include <iostream>
using namespace std;
int main()
{ long limits;
cout << "Enter a positive integer: "; cin >> limits;
cout << "Factorial numbers of "<<0<<" is " << 1<<endl;
cout << "Factorial numbers of "<<1<<" is " << 1<<endl;
long fac=1, i=1;
do //使用do-while循环
{ fac *= ++i;
cout << "Factorial numbers of "<<i<<" is " << fac<<endl;
} while (fac < limits);
return 0;
}
【案例2-17】计算数的阶乘——for循环
#include <iostream>
using namespace std;
int main()
{ long limits;
cout << "Enter a positive integer: "; cin >> limits;
cout << "Factorial numbers of "<<0<<" is " << 1<<endl;
cout << "Factorial numbers of "<<1<<" is " << 1<<endl;
long fac=1;
for(int i=2;fac<=limits;i++) //使用for 循环
{ fac *= i;
cout << "Factorial numbers of "<<i<<" is " << fac<<endl;
}
return 0;
}
【案例2-18】筛选素数——步长为2的for循环
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{ long n;
cout << "Enter a positive integer: "; cin >> n;
if (n < 2)
cout << n << " is not prime." << endl;
else if (n < 4)
cout << n << " is prime." << endl;
else if (n%2 == 0)
cout << n << " = 2*" << n/2 << endl;
else
{ for (int i=3; i <= n/2; i += 2) //步长为2
if (n%i == 0)
{cout << n << " = " << i << "*" << n/i << endl; exit(0);}
cout << n << " is prime." << endl;
}
return 0;
}
【案例2-19】输出1~20之间的偶数——continue语句
#include <iostream>
using namespace std;
int main()
{ cout<<"The even numbers are as follows:"<<endl;
for(int i=0; i<=20; i++)
{ if(i%2) continue; //根据条件使用continue结束本次循环
cout << i << ' ';
}
return 0;
}
【案例2-20】统计输入整数的个数并求和——exit()函数
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{ int sum=0,num=0,m;
cout<<"Please input integers (0:end):"<<endl;
do { cin>>m; num++; sum+=m;
if(m==0)
{ cout<<"Entered numbers:"<<num<<" integers.\n";
cout<<"The sum is:"<<sum<<endl;
exit(0); // 使用exit()函数终止程序
}
}while(1);
return 0;
}
【案例2-21】“剪刀、石头、布”游戏——枚举类型
#include <iostream>
using namespace std;
enum Choice {ROCK, CLOTH, SCISS}; //声明枚举类型Choice
enum Winner {Play1, Play2, Tie}; //声明枚举类型Winner
int main()
{ int n;
Choice cho1, cho2;
Winner winner;
cout << "Choose rock (0), cloth (1), or Sciss (2):" << endl;
cout << "Player No. 1: "; cin >> n; cho1 = Choice(n);
cout << "Player No. 2: "; cin >> n; cho2 = Choice(n);
if (cho1 == cho2) winner = Tie;
else if (cho1 == ROCK)
if (cho2 == CLOTH) winner = Play2;
else winner = Play1;
else if (cho1 == CLOTH)
if (cho2 == SCISS) winner = Play2;
else winner = Play1;
else
if (cho2 == ROCK) winner = Play2;
else winner = Play1;
if (winner == Tie) cout << "\tTied!\n";
else if (winner == Play1) cout << "\tPlayer No. 1 wins." <<endl;
else cout << "\tPlayer No. 2 wins." << endl;
return 0;
}
【案例2-22】简单的学生信息类型——结构体
#include <iostream>
#include <iomanip>
using namespace std;
struct student //学生信息结构体
{ int num;
char name[20];
char gender;
int age;
}stu1={1001,"Zhang San",'M',19};
int main()
{ student stu2={1002,"Li Si",'M',20}; //声明结构体变量并初始化
student stu3={1003,"Wang Hong",'F',22}; //声明结构体变量并初始化
cout<<setw(7)<<stu1.num<<setw(20)<<stu1.name<<setw(3)<<stu1.gender<<setw(3)<<stu1.age<<endl;
cout<<setw(7)<<stu2.num<<setw(20)<<stu2.name<<setw(3)<<stu2.gender<<setw(3)<<stu2.age<<endl;
cout<<setw(7)<<stu3.num<<setw(20)<<stu3.name<<setw(3)<<stu3.gender<<setw(3)<<stu3.age<<endl;
return 0;
}
【案例2-23】综合案例——百钱买百鸡问题
#include<iostream>
using namespace std;
int main()
{
int n=100;
cout<<"鸡公 鸡母 鸡雏"<<endl; //i表示鸡公,j表示鸡母,k表示鸡雏
for ( int i = 1; i <= n; i++ )
for ( int j = 1; j <= n; j++ )
for( int k = 1; k <= n; k++ )
if(( n == 5 * i + 3 * j + k / 3 ) && ( k % 3 == 0 ) && ( n == i + j + k ))
cout << i << " " << j << " " << k << endl;
return 0;
}
#include<stdio.h>
int main()
{
int x,y,z,j=0;
printf("Folleing are possible plans to buy 100 fowls with 100 Yuan.\n");
for(x=0;x<=20;x++) //外层循环控制鸡翁数
for(y=0;y<=33;y++) //内层循环控制鸡母数y在0~33变化
{
z=100-x-y; //内外层循环控制下,鸡雏数z的值受x,y的值的制约
if(z%3==0&&5*x+3*y+z/3==100) //验证取z值的合理性及得到一组解的合理性
printf("%2d:cock=%2d hen=%2d chicken=%2d\n",++j,x,y,z);
}
}
【案例3-1】编写输出专用函数——无参函数
#include<iostream>
using namespace std;
void DispMessage(void) //定义无参函数
{
cout<<"This is a Message!"<<endl;
}
int main()
{
DispMessage(); //调用无参函数DispMessage
return 0;
}
【案例3-2】编写求和函数——有参函数
#include<iostream>
using namespace std;
double add(double x,double y) //定义有参函数
{
double z; z=x+y; return(z);
}
int main()
{
double a=0.5, b=1.0;
cout<<"add(a,b)="<<add(a,b)<<endl; //调用有参函数add()
return 0;
}
【案例3-3】编写求和函数——函数的不同调用形式
#include<iostream>
using namespace std;
double add(double x,double y) //函数的定义,其有返回值
{
double z; z=x+y;
cout<<x<<"+"<<y<<"="<<z<<endl;
return(z);
}
int main()
{
double a=0.5,b=1.0;
//以不同参数形式调用函数add()
cout<<"add(1.5,2.5)="<<add(1.5,2.5)<<endl;
cout<<"add(a,b)="<<add(a,b)<<endl;
cout<<"add(2*a,a+b)="<<add(2*a,a+b)<<endl;
double c=2*add(a,b); //以表达式方式调用函数add()
cout<<"c="<<c<<endl;
add(2*a,b); //以语句方式调用函数add()
cout<<" add(a, add(a,b))="<<add(a, add(a,b))<<endl; //以函数参数形式调用函数add()
return 0;
}
【案例3-4】编写符号函数——函数的返回值
#include<iostream>
using namespace std;
int sgn(double x) //定义符号函数sgn(),其返回值为int类型
{
if (x>0) return(1); //返回出口1
if (x<0) return(-1); //返回出口2
return(0); //返回出口3
}
int main()
{
double x;
for (int i=0;i<=2;i++)
{
cout<<"Input x="; cin>>x;
cout<<"sgn("<<x<<")="<<sgn(x)<<endl;
}
return 0;
}
【案例3-5】编写最值函数——函数原型声明
#include<iostream>
using namespace std;
//…函数原型声明语句也可以在这里
int main()
{
float max(float,float); //max()函数原型声明语句
float a,b,Max; //变量声明语句
cout<<" Input a="; cin>>a; //输入参数a
cout<<" Input b="; cin>>b; //输入参数b
Max=max(a,b); //调用max()函数
cout<<"max("<<a<<","<<b<<")="<<Max<<endl;
return 0;
}
float max(float x,float y) {
float z; z=(x>y)?x:y;
return(z); //返回值类型为浮点型
}
【案例3-6】值传递和引用传递的区别
#include <iostream>
using namespace std;
void fun(int,int&); //函数参数一个为值传递,一个引用传递
int main()
{
int a = 22, b = 44;
cout << "Initial a = " << a << ", b = " << b << endl;
fun(a,b); cout << "After fun(a,b), a = " << a << ", b = " << b << endl;
fun(2*a-3,b); cout << "After fun(2*a-3,b), a = " << a << ", b = " << b << endl;
return 0;
}
void fun(int x, int& y)
{
x = 88; y = 99;
}
【案例3-7】编写最值函数——内联函数
#include<iostream>
using namespace std;
inline int max(int x,int y) //使用inline关键字声明max()为内联函数
{
return x>y?x:y;
}
int main()
{
int a=3,b=5,c;
c=max(a,b); cout<<"max("<<a<<","<<b<<")="<<c<<endl;
cout<<"max("<<15<<","<<11<<")="<<max(15,11)<<endl;
return 0;
}
【案例3-8】计算圆的面积和周长函数——通过引用返回多于1个的数值
#include <iostream>
using namespace std;
void ComCircle(double&, double&, double); //函数的原型声明
int main()
{
double r, a, c;
cout << "Enter radius: "; cin >> r;
ComCircle(a, c, r);
cout << "The area = " << a << ", and the circumference = " << c << endl;
return 0;
}
void ComCircle(double& area, double& circum, double r) //通过引用变量返回面积和周长
{
const double PI = 3.141592653589793;
area = PI*r*r; circum = 2*PI*r; //计算面积和周长
}
【案例3-9】最小公倍数函数——函数的嵌套调用
#include <iostream>
using namespace std;
long int gcd(long int m,long int n) //求最大公约数
{
if (m < n) swap(m,n);
while (n>0)
{
int r = m%n; m = n; n = r;
}
return m;
}
long int lcm(long int m,long int n) //求最小公倍数
{
return m*n/gcd(m,n);
}
int main()
{
int m, n;
cout << "Please input two integers: "; cin >> m >> n;
cout << "lcm(" << m << "," << n << ") = " << lcm(m,n) << endl;
return 0;
}
【案例3-10】显示函数的参数——带默认参数的函数
#include <iostream>
using namespace std;
void disp(int x=1,int y=1,int z=1) //带有默认参数值的函数
{
cout<<"Parameter 1 is: "<<x<<endl;
cout<<"Parameter 2 is: "<<y<<endl;
cout<<"Parameter 3 is: "<<z<<endl;
}
int main() //main()函数中测试参数带有默认值的函数disp()
{
cout<<"No actual parameter"<<endl; disp();
cout<<"One actual parameter"<<endl; disp(1);
cout<<"Two actual parameter"<<endl; disp(1,2);
cout<<"Three actual parameter"<<endl; disp(1,2,3);
return 0;
}
【案例3-11】通用最值函数——参数数目可变的函数
#include <iostream>
#include <cstdarg>
using namespace std;
int max(int,int...); //原型声明
int main()
{
int a,b,c,d,e;
cout<<"Enter five integers, seperate with space:"; cin>>a>>b>>c>>d>>e;
cout<<"The maxmum in a and b is:"<<max(2,a,b)<<endl;
cout<<"The maxmum in five integers is:"<<max(5,a,b,c,d,e)<<endl;
return 0;
}
int max(int num,int integer...) //定义参数数目可变的函数
{
va_list ap;
int n=integer;
va_start(ap,integer);
for(int i=1;i<num;i++)
{
int t=va_arg(ap,int);
if(t>n)
n=t;
}
va_end(ap);
return n;
}
【案例3-12】多变的最值函数——参数数目不同的重载函数
#include <iostream>
using namespace std;
int main()
{
int min (int a, int b, int c); //函数声明
int min (int a, int b); //函数声明
int i1 ,i2,i3,i;
cout<<"Enter three integers:"; cin >>i1 >>i2 >>i3; //输入3个整数
i = min(i1 ,i2) ; cout <<"The min in two intergers=" <<i <<endl; // 2个整数中最小者
i = min(i1 ,i2 ,i3) ; // 3个整数中最小者
cout <<"The min in three intergers=" <<i <<endl;
return 0;
}
int min(int a,int b,int c) //定义求3个整数中的最小者的函数
{
int k;
k=(a<b)?a:b;
k=(k<c)?k:c;
return k;
}
int min(int a,int b) //定义求2个整数中的最小者的函数
{
int k;
k=(a<b)?a:b;
return k;
}
【案例3-13】求绝对值——使用系统函数
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
void main( void )
{
int ix = -4, iy;
long lx = -41567L, ly;
double dx = -3.141593, dy;
iy = abs( ix ); cout<<"The absolute value of"<<ix <<" is "<<iy<<endl;
ly = labs( lx ); cout<<"The absolute value of"<<lx <<" is "<<ly<<endl;
dy = fabs( dx ); cout<<"The absolute value of"<<dx <<" is "<<dy<<endl;
}
【案例3-14】将整数和小数分离——使用系统函数
#include<iostream>
#include<cmath>
using namespace std;
void main(void)
{
double fraction, integer,number = 103.567;
fraction = modf(number, &integer);
cout<<number<<"整数部分为:"<<integer<<" 小数部分为:"<<fraction;
}
【案例3-15】求平方根——使用系统函数
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
void main( void )
{
double question = 45.35, answer;
answer = sqrt( question );
if( question < 0 )
cout<<"Error: sqrt returns "<<answer<<endl;
else
cout<<"The square root of "<<question<<" is "<<answer<<endl;
}
【案例3-16】求随机数——使用系统函数
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void main(void)
{
cout << "RAND_MAX=" << RAND_MAX << endl;
cout<<"产生10个 0 到 99的随机数如下:\n";
for(int i=0; i<10; i++)
cout<<(rand() % 100)<<' '; //求除以100的余数
cout << "\n使用srand:\n";
srand( (unsigned)time( NULL ) );
for( i = 0; i < 10;i++ )
cout<<rand() <<' ';
}
【案例3-17】计算时间差——使用系统函数
#include <iostream >
#include <ctime >
#include <conio.h>
using namespace std;
void main(void)
{
time_t start,end;
start = time(NULL);
cout << "请按Enter键!\n";
for (;;)
{
if (getch()=='\r')
break;
}
end = time(NULL);
cout << "按键前后相差:"<<difftime(end,start)<<" 秒";
}
【案例4-1】编写设计全部成员为public模式的类
#include<iostream>
using namespace std;
class PubClass
{public: //以下成员均为公有成员
int value; //公有数据成员
void set(int n) //公有函数成员
{
value=n;
}
int get(void) //公有函数成员
{
return value;
}
};
int main()
{
PubClass a; //创建对象
a.set(10); cout<<"a.get()="<<a.get()<<endl; //直接访问对象的公有成员函数
a.value=20; cout<<"a.value="<<a.value<<endl; //直接访问对象的公有数据成员
return 0;
}
【案例4-2】编写设计private数据访问模式的类
#include <iostream>
using namespace std;
class PriClass
{
int iv; double dv; //私有数据成员
public:
void set_PriClass(int n,double x); //公有函数成员为接口函数
void show_PriClass(char*); //公有函数成员为接口函数
};
//定义PriClass类的接口成员函数
void PriClass::set_PriClass(int n,double x) { iv=n; dv=x;}
void PriClass::show_PriClass(char *name)
{
cout<<name<<": "<<"iv=" <<iv<< ", dv=" <<dv<< endl;
}
int main()
{
PriClass obj;
obj.show_PriClass("obj"); //通过接口函数来访问数据成员
obj.set_PriClass(5,5.5); obj.show_PriClass("obj"); //通过接口函数来访问数据成员
return 0;
}
【案例4-3】编写结构体类——以结构体形式定义类
说明:结构体和类唯一区别是:结构体成员的访问权限默认为公有的,而类成员的访问权限默认为私有的
#include<iostream>
using namespace std;
struct StructClass //用struct关键字定义StructClass类
{
void set_value(int n) //公有属性
{
value=n;
}
void show_value(char *name) //公有属性
{
cout<<name<<": "<<value<<endl;
}
private: //为了保持私有属性,不能省略private
int value;
};
int main()
{
StructClass a;
a.show_value ("a"); //通过对象访问公有属性函数
a.set_value(100);
a.show_value ("a"); //通过对象访问公有属性函数
return 0;
}
【案例4-4】完善有理数类——拷贝构造函数的调用时机
#include <iostream>
using namespace std;
int gcd(int m, int n) //返回m 和n最大公约数
{
if (m<n) swap(m,n);
while (n>0) { int r=m%n; m = n; n = r; }
return m;
}
class Ratio
{
public:
Ratio(int n=0, int d=1) : num(n), den(d)
{
cout << "Common constructor called\n"; reduce();
}
Ratio(const Ratio& r):num(r.num), den(r.den) //拷贝构造函数
{
cout << "Copy constructor called\n";
}
void disp()
{
cout <<num<<"/"<<den<<endl;
}
private:
int num, den;
void reduce()
{
if (num == 0 || den == 0)
{
num = 0; den = 1; return; }
if (den < 0) {den *= -1; num *= -1; }
if (den == 1) return;
int sgn = (num<0?-1:1); int g = gcd(sgn*num,den);
num /= g; den /= g;
}
};
Ratio func(Ratio r) //初始化形参时调用拷贝构造函数
{
Ratio s = r;
return s; //返回时调用拷贝构造函数
}
int main()
{
Ratio x(20,7);
cout<<"Ratio x is:"; x.disp();
Ratio y(x); //调用拷贝构造函数,用x初始化y
cout<<"Ratio y is:"; y.disp();
cout<<"Func() Start:"<<endl;
func(y); //调用拷贝构造函数3次
cout<<"Func() End"<<endl;
return 0;
}
【案例4-5】完善的有理数类——析构函数
#include <iostream>
using namespace std;
class Ratio
{
int num, den;
public:
Ratio() {cout << "Constructor called.\n";}
Ratio(Ratio &r) { cout << "Copy constructor called.\n"; }
~Ratio() { cout << "Destructor called.\n"; }
};
int main()
{
Ratio x;
{ //x的作用域开始
Ratio y; //y的作用域开始
cout << "Now y is alive.\n";
} //y的作用域结束,调用析构函数1次
cout << "Now between blocks.\n";
{
Ratio z(x); //z的作用域开始
cout << "Now z is alive.\n";
} //z的作用域结束,调用析构函数1次
return 0;
}
//x的作用域结束,调用析构函数1次
【案例4-6】综合案例——电子日历
#include <iostream >
#include <cstdlib >
using namespace std;
class CDate //定义电子日历类
{
int m_nDay; int m_nMonth; int m_nYear; //日月年
public:
CDate(){}; //默认构造函数
CDate(int year, int month,int day ) //带参构造函数
{
SetDate(year, month, day); //调用成员函数来初始化
};
void Display(); //显示日期
void AddDay(); //返回加1后的日期
void SetDate(int year, int month, int day) //设置日期
{
m_nDay=day; m_nMonth=month; m_nYear=year;
}
~CDate() {};
private:
bool IsLeapYear() ; //判断是否为闰年
};
void CDate::Display() //显示日期
{
char day[5] ,month[5], year[5] ;
_itoa (m_nDay, day, 10) ;
_itoa (m_nMonth, month, 10) ;
_itoa(m_nYear,year, 10) ;
cout << day << "/" << month << "/" << year << endl;
}
void CDate::AddDay () //返回加1后的日期
{
m_nDay++;
if (IsLeapYear())
{
if ((m_nMonth==2) && (m_nDay==30))
{
m_nMonth++;
m_nDay=1;
return;
}
}
else
{
if((m_nMonth==2)&& (m_nDay==29))
{
m_nMonth++;
m_nDay=1;
return;
}
}
if (m_nDay>31 )
{
if(m_nMonth==12) { m_nYear++; m_nMonth=1 ; m_nDay=1 ; }
else { m_nMonth++; m_nDay=1 ; }
}
}
bool CDate::IsLeapYear() //判断是否为闰年
{
bool bLeap;
if(m_nYear%4!=0) bLeap=false;
else if(m_nYear%100!=0) bLeap=true;
else if(m_nYear%400!=0) bLeap=false;
else bLeap=true;
return bLeap;
}
void main ()
{
CDate d (2010,4,6); //调用构造函数初始化日期
cout << "Current date:";
d.Display();
d.AddDay();
cout << "Add 1 to Current date:";
d.Display();
d. SetDate(2010,4,8); //调用成员函数重新设置日期
cout << "After reset Date,the date:";
d.Display();
}
【案例5-1】局部作用域的效果
#include <iostream>
using namespace std;
void fun() //变量num将在每次进入函数fun()时进行初始化
{
int num = 10;
cout << num << "\n";
num++; // 这个语句没有持续效果
}
int main()
{
for(int i=0; i < 3; i++)
fun();
return 0;
}
【案例5-2】屏蔽效应——作用域效果导致的名称隐藏
#include <iostream>
using namespace std;
int main()
{
int i = 10, j = 30;
if(j > 0)
{
int i; // 内部的i 将隐藏或屏蔽外层的i
i = j / 2;
cout << "inner variable i: " << i << '\n';
}
cout << "outer variable i: " << i << '\n';
return 0;
}
【案例5-3】筛选偶数——文件作用域变量
#include <iostream>
using namespace std;
int count; //这是一个全局变量
void func1()
{
void func2();
cout << "count: " << count<< '\n'; //可以访问全局变量count
func2();
}
void func2()
{
int count; //这是一个局部变量
for(count=0; count<2; count++)
cout << '*';
}
int main()
{
void func1();
void func2();
int i; //这是一个局部变量
for(i=0; i<10; i++)
{
count = i++;
func1();
}
return 0;
}
【案例5-4】求数据序列的平均值——static局部变量的持续效果
#include <iostream>
using namespace std;
int Average(int i)
{
static int sum = 0, count = 0; //声明静态局部变量,具有全局寿命,局部可见
sum = sum + i; count++;
return sum/count;
}
int main()
{
int num; //局部变量,具有动态生存期
do
{
cout << "Enter numbers (-1 to quit): "; cin >> num;
if(num != -1)
cout << "Running average is: " << Average(num);
cout <<endl;
} while(num > -1);
return 0;
}
【案例5-5】求数据序列的平均值——static全局变量的应用
#include <iostream>
using namespace std;
int Average(int i);
void reset();
int main()
{
int num; //局部变量,具有动态生存期
do
{
cout << "Enter numbers (-1 to quit, -2 to reset): ";
cin >> num;
if(num == -2)
{
reset();
continue;
}
if(num != -1)
cout << "Running average is: " << Average(num);
cout << endl;
} while(num != -1);
return 0;
}
static int sum = 0, count = 0; //静态全局变量,具有静态生存期,全局可见
int Average(int i)
{
sum = sum + i; count++; return sum/count;
}
void reset()
{
sum = 0; count = 0;
}
【案例5-6】时钟类——具有静态生存期的全局变量和全局对象
#include<iostream>
using namespace std;
int h=0,m=0,s=0; //声明全局变量,具有静态生存期
class Clock
{
public:
Clock();
void SetTime(int NewH, int NewM, int NewS); //三个形参均具有函数原型作用域
void ShowTime();
~Clock(){}
private:
int Hour,Minute,Second;
};
Clock::Clock()
{
Hour=h; Minute=m; Second=s; //使用全局变量初始化
}
void Clock::SetTime(int NewH, int NewM, int NewS)
{
Hour=NewH; Minute=NewM; Second=NewS;
}
void Clock::ShowTime()
{
cout<<Hour<<":"<<Minute<<":"<<Second<<endl;
}
Clock globClock; //声明对象globClock,具有静态生存期,文件作用域
int main()
{
cout<<"Initial time output:"<<endl;
//引用具有文件作用域的对象globClock:
globClock.ShowTime(); //对象的成员函数具有类作用域
globClock.SetTime(10,20,30); //将时间设置为10:20:30
//调用拷贝构造函数,以globClock为初始值
Clock myClock(globClock); //声明具有块作用域的对象myClock
cout<<"Setted time output:"<<endl;
myClock.ShowTime(); //引用具有块作用域的对象myClock
return 0;
}
【案例5-7】实现数据共享——公有静态数据成员
#include <iostream>
using namespace std;
class PubClass
{
public:
static int num; //公有静态数据成员的声明
void shownum() { cout << "The num is:"<<num << endl; }
};
int PubClass::num; //在类外定义num
int main()
{
PubClass a, b;
PubClass::num = 1000; //通过类名访问静态成员num
a.shownum();
b.shownum();
a.num = 2000; //通过对象访问静态成员num
a.shownum();
b.shownum();
return 0;
}
【案例5-8】实现数据共享——私有型静态数据成员
#include <iostream>
using namespace std;
class PriClass
{
static int num; //私有型静态成员
public:
void setnum(int i) { num = i; };
void shownum() { cout << "The num is:"<<num << "\n"; }
};
int PriClass::num; //在类外定义 num
int main()
{
PriClass a, b;
a.shownum(); b.shownum();
a.setnum(1000); //设置静态成员num为1000
a.shownum(); b.shownum();
return 0;
}
【案例5-9】实现函数共享——静态函数成员
#include <iostream>
using namespace std;
class FunClass
{
static int count; //静态数据成员声明
public:
FunClass() { count++; cout << "Constructing object " <<count << endl; }
~FunClass() { cout << "Destroying object " << count << endl; count--; }
static int GetCount() { return count; } //静态函数成员
};
int FunClass::count; //静态数据成员定义
int main()
{
FunClass a, b, c;
cout << "From Class, there are now " << FunClass::GetCount() << " in existence.\n";
cout << "From Object, there are now " << a.GetCount() <<" in existence.\n";
return 0;
}
【案例5-10】求最小公因子——友元函数的访问类的私有成员
#include <iostream>
using namespace std;
class FriFunClass
{
int a, b;
public:
FriFunClass(int i, int j) { a=i; b=j; }
friend int FriFun(FriFunClass x); //友元成员函数
};
int FriFun(FriFunClass x) //注意:FriFun() 不是任何类的成员函数
{
//由于函数FriFun() 是类FriFunClass的友元函数,所以它不能直接访问a和b
int max = x.a < x.b ? x.a : x.b;
for(int i=2; i <= max; i++)
if((x.a%i)==0 && (x.b%i)==0)
return i;
return 0;
}
int main()
{
FriFunClass n(10, 20); //声明类对象
if(FriFun(n))
cout << "Common denominator is " <<FriFun(n) << "\n";
else cout << "No common denominator.\n";
return 0;
}
【案例5-11】判断圆柱体和立方体的颜色是否相同——多个类共享友元函数
#include <iostream>
using namespace std;
class Cylinder; // 前向引用声明
enum Colors { red, green, yellow }; //定义颜色枚举类型
class Cube
{
Colors color;
public:
Cube(Colors c) { color = c; }
friend bool TestSame(Cube x, Cylinder y); //声明为Cube的友元函数
};
class Cylinder
{
Colors color;
public:
Cylinder(Colors c) { color= c; }
friend bool TestSame(Cube x, Cylinder y); //声明为Cylinder的友元函数
};
bool TestSame(Cube x, Cylinder y)
{
if(x.color == y.color)
return true;
else return false;
}
int main()
{
Cube cube1(red), cube2(yellow);
Cylinder cyl(yellow); //声明对象并初始化
if(TestSame(cube1, cyl))
cout << "The color of cube1 and cyl are the same.\n";
else
cout << "The color of cube1 and cyl are different.\n";
if(TestSame(cube2, cyl))
cout << "The color of cube2 and cyl are the same.\n";
else
cout << "The color of cube2 and cyl are different.\n";
return 0;
}
【案例5-12】计算2个三角形之和——友元函数的应用
#include <iostream>
#include <cmath>
using namespace std;
class Trig
{
double x,y,z;
double area() {double d=(x+y+z)/2; return sqrt(d* (d-x)* (d-y)* (d-z)) ; }
public :
Trig (int i,int j,int k) { x=i;y=j;z=k; }
int isTriangle() //判断是否构成三角形
{
if (x+y>z && x+z>y && y+z>x)
return 1 ;
else
return 0;
}
friend double twoarea(Trig tl,Trig t2) //声明友元函数
{
return tl.area()+t2.area() ;
}
};
int main()
{
Trig tl (3,5,7) ,t2 (8, 7, 12) ;
if (tl.isTriangle() && t2.isTriangle())
cout << "Total area of two Triangles:" << twoarea(tl,t2) << endl;
else
cout << "Cannot form a Triangle"<< endl;
return 0;
}
【案例5-13】数据的单向传递——常引用作函数形参
#include <iostream>
using namespace std;
//常引用作形参,在函数中不能更新z所引用的对象,因此对应的实参不会被破坏。
void fun(int x, int& y, const int& z)
{
x += z;
y += z;
cout << "x = " << x << ", y = " << y << ", z = " << z << endl;
}
int main()
{
int a = 20, b = 30, c = 40;
cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
fun(a,b,c);
cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
fun(2*a-3,b,c);
cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
return 0;
}
【案例5-14】成员函数的选择调用——常成员函数
#include<iostream>
using namespace std;
class ZRF
{
public:
ZRF(int Z1, int Z2){ZRF1=Z1;ZRF2=Z2;}
void disp();
void disp() const; //常成员函数声明
private:
int ZRF1,ZRF2;
};
void ZRF::disp()
{
cout<<ZRF1<<":"<<ZRF2<<endl;
}
void ZRF::disp() const //常成员函数定义
{
cout<<ZRF1<<":"<<ZRF2<<endl;
}
int main()
{
ZRF a(2,3);
a.disp(); //调用void disp()
const ZRF b(10,20);
b.disp(); //调用void disp() const
return 0;
}
【案例5-15】计算圆周长——不带参数的宏定义
#include<iostream>
using namespace std;
#define PI 3.14159 //宏名PI为符号常量
#define n a //宏名n将用a来替换
#define LENGTH 2*PI*n // 宏名LENGTH将用2*PI*n来替换
int main()
{
int n=1; //int n=1;替换为int a=1;
cout<<"LENGTH="<<LENGTH<<endl; //替换为cout<<"LENGTH="<<2*3.14159*a<<endl;
return 0;
}
【案例5-16】求三角形面积——带参数的宏函数
#include<iostream>
#include<cmath>
using namespace std;
#define s(a,b,c) (a+b+c)/2 //带参数的宏
#define area(a,b,c) sqrt(s(a,b,c)*(s(a,b,c)-a)*(s(a,b,c)-b)*(s(a,b,c)-c)) //带参数的宏
int main()
{
float x=4,y=5,z=6;
cout<<"The area is :"<<area(x,y,z)<<endl; //编译时发生宏替换
cout<<"The area is :"<<area(5,4,3)<<endl; //编译时发生宏替换
return 0;
}
【案例5-17】求最小值——带参数的宏函数和内联函数
#include<iostream>
using namespace std;
inline min(int x,int y,int z ) //内联函数
{
int min=x;
if(y<min) min=y;
if(z<min) min=z;
return min;
}
#define MIN(a,b) ((a)<(b)?(a):(b)) //宏函数
#define min(a,b,c) MIN(a,MIN(c,b)) //宏函数
int main()
{
cout<<"The min value is:"<<(min)(4,5,3.0)<<endl; //调用内联函数
cout<<"The min value is:"<<min(5.0,4,3.0)<<endl; //调用宏函数
return 0;
}
【案例5-18】程序调试阶段的条件编译#ifndef-#else-#endif
#include<iostream>
using namespace std;
#define RUN //语句1:在调试程序时使之成为注释行
int main()
{
int x=1,y=2,z=3;
#ifndef RUN //语句2:本行为条件编译命令
cout<<"x="<<x<<",y="<<y<<",z="<<z; //语句3:在调试程序时需要输出信息
#endif //语句4:本行为条件编译命令
cout<<"x*y*z="<<x*y*z<<endl;
return 0;
}
【案例5-19】综合案例——统计银行存款问题
#include <iostream>
using namespace std;
class BBank; //前向引用声明
class GBank; //前向引用声明
class CBank //声明中国银行类
{
int balance;
public :
CBank() { balance=0; } //默认构造函数
CBank(int b) { balance=b; } //构造函数
void getbalance() {cout << "Input the savings in China Bank:"; cin >> balance; }
void disp() {cout << "The savings in China Bank is:" << balance << endl;}
friend void total(CBank, BBank, GBank) ;
};
class BBank //声明工商银行类
{
int balance;
public:
BBank() { balance=0; } //默认构造函数
BBank(int b) { balance=b; } //构造函数
void getbalance() { cout << "Input the savings in Business Bank:"; cin >> balance; }
void disp() {cout << "The savings in Business Bank is:"<< balance << endl;}
friend void total(CBank, BBank, GBank) ;
};
class GBank //声明农业银行类
{
int balance;
public :
GBank() { balance=0; } //默认构造函数
GBank(int b) { balance=b; } //构造函数
void getbalance()
{cout << "Input the savings in Agriculture Bank:"; cin >> balance; }
void disp()
{ cout << "The savings in Agriculture Bank is:" << balance << endl; }
friend void total(CBank, BBank, GBank) ;
};
void total(CBank A, BBank B, GBank C)
{
cout << "Total savings is:"<< A.balance+B.balance+C.balance << endl;
}
int main()
{
CBank X(100) ;
BBank Y;
GBank Z ;
X.disp () ;
Y.disp () ;
Z.disp ( ) ;
Y.getbalance () ;
Z.getbalance () ;
total (X, Y, Z) ;
return 0;
}
【案例6-1】构建向量——通过下标访问一维数组
#include <iostream>
using namespace std;
int main()
{
int Array[5]; //声明存放5个整型元素的数组
for(int t=0; t<5; ++t) Array[t] = t; //存储整型数值到数组中
for(t=0; t<5; ++t)
cout << "This is Array[" << t << "]: " << Array[t] << "\n"; //显示数组元素
return 0;
}
【案例6-2】逆序重排数组元素——使用符号常量定义数组大小
#include <iostream>
using namespace std;
int main()
{
const int SIZE=5; //定义符号常量用于设置数组大小
double Array[SIZE]; //将数组元素声明为双精度型
cout << "Enter " << SIZE << " numbers:\t";
for (int i=0; i<SIZE; i++)
cin >> Array[i]; //使用符号常量控制循环次数
cout << "In reverse order: ";
for (i=SIZE-1; i>=0; i--) //使用符号常量控制循环次数
cout << " " << Array[i];
return 0;
}
【案例6-3】计算数组元素个数——数组初始化及sizeof的使用
#include <iostream>
using namespace std;
int main()
{
float Array[] = { 10, 20, 30 }; //数组初始化
int size = sizeof(Array)/sizeof(float); //求数组的实际大小
for (int i=0; i<size; i++) cout << "Array[" << i << "] = " << Array[i] << endl;
return 0;
}
【案例6-4】垃圾数据的由来——未初始化的数据
#include <iostream>
using namespace std;
int main()
{
const int SIZE=5; //定义数组大小
float Array[SIZE]; //声明浮点型数组
for (int i=0; i<SIZE; i++)
cout << "Array[" << i << "] = " << Array[i] << endl;
return 0;
}
【案例6-5】构建n个元素的数组并输出——通过函数输入和输出数组元素
#include <iostream>
using namespace std;
void Input(int Array[], int& n) //读入n个元素到数组Array[]中
{
cout << "Enter integers. Terminate with 0:\n";
n = 0;
do
{
cout << "Array[" << n << "]: "; cin >> Array[n];
} while (Array[n++] != 0);
--n; //不计 0
}
void Output(int Array[], int n) //输出数组中的前 n个元素
{
for (int i=0; i<n; i++)
cout << Array[i] << " ";
}
int main()
{
const int MAXSIZE=100;
int Array[MAXSIZE]={0}, size;
Input(Array,size);
cout << "The array has " << size << " elements: ";
Output(Array,size);
return 0;
}
【案例6-6】气温记录——使用枚举常量定义和访问数组
#include <iostream>
using namespace std;
int main()
{
enum Day { SUN, MON, TUE, WED, THU, FRI, SAT }; //定义枚举类型
float high[SAT+1] = {80.0, 90.0, 91.0, 80.9, 90.4, 90.5, 80.7}; //使用枚举类型
for (int day = SUN; day <= SAT; day++)
cout << "The high temperature for day " << day<< " was " << high[day] << endl;
return 0;
}
【案例6-7】列数可变的矩阵——二维数组作为函数的参数
#include <iostream>
using namespace std;
void Input(int Array[][5], int n) //输入二维数组
{
cout << "Enter 15 integers, 5 per row:\n";
for (int i=0; i<n; i++)
{
cout << "Row " << i << ": ";
for (int j=0; j<5; j++)
cin >> Array[i][j];
}
}
void Output(const int Array[][5], int n) //输出二维数组
{
for (int i=0; i<n; i++)
{
for (int j=0; j<5; j++)
cout << " " << Array[i][j];
cout << endl;
}
}
int main()
{ int Array[3][5];
Input(Array, 3); Output(Array, 3); //输入输出二维数组
return 0;
}
【案例6-8】对象数组的初始化
#include <iostream>
using namespace std;
class ArrayElem
{
int x;
public:
ArrayElem(int i) { x = i; } //带有参数的构造函数
int getx() { return x; }
};
int main()
{
ArrayElem obs[4] = { -1, -2, -3, -4 }; //简化的初始化对象数组方式
for(int i=0; i < 4; i++)
cout << "obs[" << i << "].getx(): " << obs[i].getx() << "\n";
return 0;
}
【案例6-9】统计三维数组中零数值的个数——三维数组初始化
#include <iostream>
using namespace std;
int NumZeros(int Array[][4][3], int n1, int n2, int n3) //统计三维数组中零数值个数
{
int count = 0;
for (int i = 0; i < n1; i++)
for (int j = 0; j < n2; j++)
for (int k = 0; k < n3; k++)
if (Array[i][j][k] == 0)
++count;
return count;
}
int main()
{
int Array[2][4][3]= { { {5,0,2}, {0,0,9}, {4,1,0}, {7,0,7}},
{ {3,0,0}, {8,0,0}, {0,0,0}, {2,0,9} }};
cout << "This array has " << NumZeros(Array,2,4,3) << " zeros.\n";
return 0;
}
【案例6-10】输出变量的地址——取地址运算符&
#include <iostream>
using namespace std;
int main()
{
float f=44.4f;
cout << "The value of f is:" << f << endl; //输出变量f的值
cout << "The address of f is:" << &f << endl; //输出变量f的地址
return 0;
}
【案例6-11】多个名称的由来
#include <iostream>
using namespace std;
int main()
{
int n=10; int& sn=n; // sn是变量 n的别名
cout << "&n = " << &n << ", &sn = " << &sn << endl;
int& sn2=sn; // sn2是变量 n的另一个别名
int& sn3=sn2; // sn3是变量 n的另一个别名
cout << "&sn2 = " << &sn2 << ", &sn3 = " << &sn3 << endl;
return 0;
}
【案例6-12】取地址和取内容——存放地址的指针变量
#include <iostream>
using namespace std;
int main()
{
int n=10;
cout << "n = " << n << ", &n = " << &n << endl;
int* pn=&n; //pn 保存了 n的地址
cout << " pn = " << pn << endl;
cout << "&pn = " << &pn << endl; //输出地址
cout << "*pn = " << *pn << endl; //输出数值
return 0;
}
【案例6-13】求最大值——返回引用类型的函数
#include <iostream>
using namespace std;
int& FindMax(int& m, int& n)
{
return (m > n ? m : n); //返回类型是指向int类型的引用
}
int main()
{
int m = 10, n = 20;
cout << m << ", " << n << ", The max is:" << FindMax(m,n) << endl;
FindMax(m,n) = 50; //将m的值从10变为50
cout << m << ", " << n << ", The max is:" << FindMax(m,n) << endl;
return 0;
}
【案例6-14】通用的指针——void类型指针
#include <iostream>
using namespace std;
int main()
{
void *pv; //可以声明void类型的指针
int i=10,*pi;
pv = &i; //void类型指针指向整型变量
pi = (int *)pv; //类型强制转换:void类型指针赋值给int类型指针
cout<<"pv="<<pv<<endl;
//cout<<"*pv="<<*pv<<endl; //错误2:不能使用取值操作符作用于void指针变量
cout<<"pi="<<pi<<endl <<"*pi="<<*pi<<endl;
return 0;
}
【案例6-15】判断两个指针是否指向同一内存地址——指针的关系运算
#include <iostream>
using namespace std;
int main()
{
double a,b;
double *p=&a,*q=&b;
//判断两个指针是否指向同一块内存位置
if (p==q)
cout<<"The pointer of p is equal to q"<<endl;
else if(p>q)
cout<<"The address of a :"<<p<<" is larger than the address of b:"<<q;
else
cout<<"The address of a :"<<p<<" is smaller than the address of b:"<<q;
return 0;
}
【案例6-16】矩阵的创建于输出——指针数组
#include <iostream>
using namespace std;
int main()
{
int Array[3][2]={{1,2},{3,4},{5,6}};
int *pa[3];
for(int i=0;i<3;i++)
pa[i]=Array[i]; //语句1:为指针数组赋值(地址)
for(int j=0;j<3;j++)
{ for(i=0;i<2;i++,pa[j]++) //语句2:pa[j]++使指针指向下一个元素
cout<<"Array["<<j<<"]["<<i<<"]="<<*pa[j]<<"\t";
cout<<endl;
}
return 0;
}
【案例6-17】交换函数——函数参数的传值和传址调用
#include <iostream >
using namespace std;
void swap(int v1,int v2)
{
int tmp=v2;
v2=v1;
v1=tmp;
cout<<"Call swap(int,int)";
}
void swap(int *v1,int *v2)
{
int tmp=*v2;
*v2=*v1;
*v1=tmp;
cout<<"Call swap(int*,int*)";
}
int main()
{
int i = 10,j = 20, *pi = &i,*pj = &j;
cout <<"Initializing..."<<endl;
swap(&i, &j);
cout << *pi << ',' << *pj << endl; //语句1:调用函数swap(int *v1,int *v2)
swap(*pi, *pj);
cout << *pi << ',' << *pj << endl; //语句2:调用函数swap(int v1,int v2)
swap(pi, pj);
cout << *pi << ',' << *pj << endl; //语句3:调用函数swap(int *v1,int *v2)
return 0;
}
【案例6-18】可选择的加减乘除运算——函数指针数组
#include <iostream >
#include <cstdlib>
using namespace std;
int add (int x,int y) //定义函数add
{
cout<<x<<" + "<<y<<" = ";
return x+y;
}
int sub (int x,int y) //定义函数sub
{
cout<<x<<" - "<<y<<" = ";
return x-y;
}
int mult (int x,int y) //定义函数mult
{
cout<<x<<" * "<<y<<" = ";
return x*y;
}
int dev (int x,int y) //定义函数dev
{
cout<<x<<" / "<<y<<" = ";
return x/y;
}
void DispResult(int a, int b, int (*fun)(int,int))
{
cout<<fun(a,b)<<endl;
}
int main()
{
int (*funp[4])(int,int)={add,sub,mult,dev}; //语句1:定义一个函数指针数组
char op;
int a,b;
cout<<"Please intput the expression a + b:\n";
cin>>a>>op>>b;
switch(op)
{
case '+': DispResult(a,b,funp[0]); break;//语句2:使用funp调用函数add
case '-': DispResult(a,b,funp[1]); break; //语句3:使用funp调用函数sub
case '*': DispResult(a,b,funp[2]); break; //语句4:使用funp调用函数mult
case '/': DispResult(a,b,funp[3]); break; //语句5:使用funp调用函数dev
default: cout<<"Operator is illegal;\n";
}
return 0;
}
【案例6-19】指向对象的指针
#include <iostream>
using namespace std;
class NumClass
{
int num;
public:
void set_num(int val) { num = val; }
void show_num(){ cout << "The num is:"<<num << "\n"; }
};
int main()
{ NumClass ob, *p; //声明一个对象和指向对象的指针
ob.set_num(10);
ob.show_num(); //通过对象ob直接调用成员函数
p = &ob; //使对象指针p指向对象ob
p->set_num(20);
p->show_num(); //通过指针调用成员函数
return 0;
}
【案例6-20】显式使用this指针访问数据成员
#include <iostream>
using namespace std;
class ThisPointer
{
int x;
public:
ThisPointer( int = 0 ); //带默认形参值的构造函数
void Disp() const;
};
ThisPointer::ThisPointer( int value ): x( value ) { } //构造函数初始化数据成员x
void ThisPointer::Disp() const
{
cout << " x = " << x; //语句1:隐式使用this指针
cout << "\n this->x = " << this->x; //语句2:显式使用this指针
cout << "\n(*this).x = " << ( *this ).x << endl; //语句3:显式使用this指针
}
int main()
{
ThisPointer ThisObject( 10 );
ThisObject.Disp();
return 0;
}
【案例6-21】学生成绩单——多维动态数组
#include<iostream>
using namespace std;
int main()
{
int n,i,j;
float (*p)[6],*q; //语句1:声明数组指针
cout<<"Please input the number of the student:";
cin>>n;
p=new float[n][6]; //语句2:为数组动态分配内存空间
for(i=0;i<n;i++)
{
cout<<"Input student No."<<i+1<<"scores:\n";
q=p[i]; q[4]=0;
for(j=0;j<4;j++)
{
cout<<"Score No. "<<j+1<<":";
cin>>q[j];
q[4]+=q[j];
}
q[5]=q[4]/4;
}
cout<<"No. \tSc1\tSc2\tSc3\tSc4\tTotal\tAverage\n\n";
for(i=0;i<n;i++)
{
cout<<i+1; q=p[i];
for(j=0;j<6;j++)
cout<<'\t'<<q[j];
cout<<endl;
}
delete [] p; //语句3:释放动态数组
return 0;
}
【案例6-22】转换字符串字母的大小写——toupper()和tolower()函数
#include <iostream>
#include <cctype>
using namespace std;
int main()
{
char str[80] = "This Is A Test";
cout << "Original string: " << str << "\n";
for(int i = 0; str[i]; i++)
{
if(isupper(str[i]))
str[i] = tolower(str[i]); //将大写字母转换为小写
else if(islower(str[i]))
str[i] = toupper(str[i]); //将小写字母转换为大写
}
cout << "Inverted-case string: " << str;
return 0;
}
【案例6-23】拷贝字符串——strcpy()和strncpy()
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char stra[] = "Happy Birthday to You",strb[ 25 ], strc[ 15 ];
strcpy( strb, stra ); // 将stra 的内容拷贝到strb中
cout << "The string in array stra is: " << stra
<< "\nThe string in array strb is: " << strb << '\n';
strncpy( strc, stra, 14 ); //将stra 中前14个字符拷贝到strc 中不拷贝空字符
strc[ 14 ] = '\0'; // 添加 '\0'到strc中
cout << "The string in array strc is: " << strc << endl;
return 0;
}
【案例6-24】比较字符串——strcmp()和strncmp()
#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;
int main()
{
char *str1 = "Happy New Year";
char *str2 = "Happy New Year";
char *str3 = "Happy Holidays";
//使用比较字符串函数strcmp
cout <<"strcmp(str1, str2) = " << setw( 2 ) << strcmp( str1, str2 )
<< "\nstrcmp(str1, str3) = " << setw( 2 ) << strcmp( str1, str3 )
<< "\nstrcmp(str3, str1) = " << setw( 2 ) << strcmp( str3, str1 )<<endl;
//使用比较字符串函数strncmp
cout<< "strncmp(str1, str3, 6) = " << setw( 2 ) << strncmp( str1, str3, 6 )
<< "\nstrncmp(str1, str3, 7) = " << setw( 2 ) << strncmp( str1, str3, 7 )
<< "\nstrncmp(str3, str1, 7) = " << setw( 2 ) << strncmp( str3, str1, 7 ) << endl;
return 0;
}
【案例6-25】字符串的比较——String类的使用
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1( "Testing the comparison functions." );
string str2( "Hello" ),str3( "stinger" ),str4( str2 );
cout<< "str1: " << str1 << "\nstr2: " << str2
<< "\nstr3: " << str3 << "\nstr4: " << str4 << "\n";
if ( str1 == str4 )
cout << "str1 == str4\n"; //语句1:比较str1 和str4
else
{
if ( str1 > str4 )
cout << "str1 > str4\n";
else
cout << "str1 < str4\n";
}
int result = str1.compare( str2 ); //语句2:比较str1 和str2
if ( result == 0 )
cout << "str1.compare( str2 ) == 0\n";
else
if ( result > 0 )
cout << "str1.compare( str2 ) > 0\n";
else
cout << "str1.compare( str2 ) < 0\n";
result=str1.compare(2, 5, str3, 0, 5 ); //语句3:比较str1 (元素2-5) 和str3 (元素0-5)
if ( result == 0 )
cout << "str1.compare( 2, 5, str3, 0, 5 ) == 0\n";
else
if ( result > 0 )
cout << "str1.compare( 2, 5, str3, 0, 5 ) > 0\n";
else
cout << "str1.compare( 2, 5, str3, 0, 5 ) < 0\n";
result = str4.compare( 0, str2.length(), str2 ); //语句4:比较 str2 和str4
if ( result == 0 )
cout << "str4.compare( 0, str2.length(), " << "str2 ) == 0\n";
else
if ( result > 0 )
cout << "str4.compare( 0, str2.length(), " << "str2 ) > 0\n";
else
cout << "str4.compare( 0, str2.length(), str2 ) < 0\n";
result = str2.compare( 0, 3, str4 ); //语句5:比较 str2 和str4
if ( result == 0 )
cout << "str2.compare( 0, 3, str4 ) == 0\n";
else
if ( result > 0 )
cout << "str2.compare( 0, 3, str4 ) > 0\n";
else
cout << "str2.compare( 0, 3, str4 ) < 0\n";
return 0;
}
【案例6-26】综合案例——棋盘游戏
#include <iostream>
using namespace std;
class Chess
{
char ChessMat[3][3]; //棋盘游戏矩阵
public:
char CheckWin(void); //判断是否出现了获胜者
void InitChess(void); //初始化矩阵
void PlayerMove(void); //获取下棋者的走的位置
void ComputerMove(void); //获取计算机走的位置
void PrintChessMat(void); //在屏幕上输出矩阵
};
void Chess::InitChess(void) //初始化矩阵
{
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
ChessMat[i][j] = ' ';
}
void Chess::PlayerMove(void) //获取下棋者的走的位置
{
int x, y;
cout<<"Move your chessman to X Y coordinates : ";
cin>>x>>y;
x--;
y--;
if(ChessMat[x][y]!= ' ')
{
cout<<"Invalid move, try again.\n";
PlayerMove();
}
else
ChessMat[x][y] = 'X';
}
void Chess::ComputerMove(void) //获取计算机走的位置
{
int i,j;
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
if(ChessMat[i][j]==' ')
break;
if(ChessMat[i][j]==' ')
break;
}
if(i*j==9)
{
cout<<"draw\n";
exit(0);
}
else
ChessMat[i][j] = 'O';
}
void Chess::PrintChessMat(void) //在屏幕上输出矩阵
{
for(int t=0; t<3; t++)
{
cout<<ChessMat[t][0]<<" | "<<ChessMat[t][1]<<" | "<<ChessMat[t][2];
if(t!=2)
cout<<"\n---|---|---\n";
}
cout<<"\n";
}
char Chess::CheckWin(void) //判断是否出现了获胜者
{
for(int i=0; i<3; i++) //检查行
if(ChessMat[i][0]==ChessMat[i][1] && ChessMat[i][0]==ChessMat[i][2])
return ChessMat[i][0];
for(i=0; i<3; i++) //检查列
if(ChessMat[0][i]==ChessMat[1][i] && ChessMat[0][i]==ChessMat[2][i])
return ChessMat[0][i];
//检查对角线
if(ChessMat[0][0]==ChessMat[1][1] && ChessMat[1][1]==ChessMat[2][2])
return ChessMat[0][0];
if(ChessMat[0][2]==ChessMat[1][1] && ChessMat[1][1]==ChessMat[2][0])
return ChessMat[0][2];
return ' ';
}
int main()
{
Chess chess;
char done = ' ';
cout<<"Game beginning.\n" <<"You will play against the computer.\n";
chess.InitChess();
do
{
chess.PrintChessMat();
chess.PlayerMove();
done = chess.CheckWin();
if(done!= ' ')
break;
chess.ComputerMove();
done = chess.CheckWin();
} while(done== ' ');
if(done=='X')
cout<<"You won!\n";
else
cout<<"I won!\n";
chess.PrintChessMat(); //显示最终位置
return 0;
}
【案例7-1】公有继承中成员的访问
#include <iostream>
using namespace std;
class Base
{
int x,y; //私有数据成员
protected:
int a,b; //保护数据成员
public:
int m,n; //公有数据成员
void SetX(int X) {x=X;} //为私有数据成员设置接口
void SetY(int Y) {y=Y;} //为私有数据成员设置接口
int GetX(){return x;} //为私有数据成员设置接口
int GetY(){return y;} //为私有数据成员设置接口
};
class Derived:public Base //以公有方式继承基类
{
public:
void SetXY(int X, int Y) {SetX(X); SetY(Y);} //语句1:使用基类接口函数设置数据
void SetAB(int A, int B) {a=A; b=B;} //派生类可以直接访问基类的保护数据
void SetMN(int M, int N) {m=M; n=N;} //派生类可以直接访问基类的公有数据
int GetSumXY() {return (GetX()+GetY());} //语句2:使用基类接口函数提取数据
int GetSumAB() {return (a+b);} //派生类可以直接访问基类的保护数据
int GetSumMN() {return (m+n);} //派生类可以直接访问基类的公有数据
};
int main()
{
Derived objD;
objD.SetXY(1,2);
objD.SetAB(10,20);
objD.SetMN(100,200);
cout<<"X+Y="<<objD.x+objD.y<<endl; //错误,派生类对象不能直接访问私有数据
cout<<"A+B="<<objD.a+objD.b<<endl; //错误,派生类对象不能直接访问保护数据
cout<<"M+N="<<objD.m+objD.n<<endl; //派生类对象可以直接访问公有数据
return 0;
}
【案例7-2】多级继承中保护继承效果
#include <iostream>
using namespace std;
class Base
{
int x,y; //私有数据成员
protected:
int a,b; //保护数据成员
public:
int m,n; //公有数据成员
void SetX(int X) {x=X;} //为私有数据成员设置接口
void SetY(int Y) {y=Y;} //为私有数据成员设置接口
int GetX(){return x;} //为私有数据成员设置接口
int GetY(){return y;} //为私有数据成员设置接口
};
class ExtBase:protected Base{}; //一级继承为保护继承
class Derived:public ExtBase
{
public:
void SetXY(int X, int Y) {SetX(X); SetY(Y);}
void SetAB(int A, int B) {a=A; b=B;}
void SetMN(int M, int N) {m=M; n=N;}
int GetSumXY() {return (GetX()+GetY());}
int GetSumAB() {return (a+b);}
int GetSumMN() {return (m+n);}
};
int main()
{ Derived objD;
objD.SetXY(1,2);
objD.SetAB(10,20);
objD.SetMN(100,200);
cout<<"X+Y="<<objD.GetSumXY()<<endl;
cout<<"A+B="<<objD.GetSumAB()<<endl;
cout<<"M+N="<<objD.GetSumMN()<<endl;
return 0;
}
【案例7-3】多继承中默认构造函数与析构函数的调用
#include <iostream>
using namespace std;
class Base1
{
public:
Base1(void) {cout<<"Base1 constructor called"<<endl;}
~Base1(void) {cout<<"Base1 destructor called"<<endl;}
};
class Base2
{
public:
Base2(void) {cout<<"Base2 constructor called"<<endl;}
~Base2(void) {cout<<"Base2 destructor called"<<endl;}
};
class Derived:public Base1,public Base2
{
public:
Derived(void):Base1(),Base2() {cout<<"Derived constructor called"<<endl;}
~Derived(void) {cout<<"Derived destructor called"<<endl;}
};
int main()
{
Derived objD;
{ //块作用域1开始
Base1 objB1;
{ //块作用域2开始
Base2 objB2;
} //块作用域2结束
} //块作用域1结束
return 0;
}
【案例7-4】包含内嵌对象的多级多继承派生类的构造函数和析构函数调用顺序
#include <iostream>
using namespace std;
class Base
{
public:
Base(int i) {cout<<"Base constructor called "<<i<<endl;}
~Base(void) {cout<<"Base destructor called"<<endl;}
};
class Base1:public Base
{
public:
Base1(int i,int j):Base(j) {cout<<"Base1 constructor called "<<i<<endl;}
~Base1(void) {cout<<"Base1 destructor called"<<endl;}
};
class Base2
{
public:
Base2(int i) {cout<<"Base2 constructor called "<<i<<endl;}
~Base2(void) {cout<<"Base2 destructor called"<<endl;}
};
class Base3
{
public:
Base3(int i) {cout<<"Base3 constructor called "<<i<<endl;}
~Base3(void) {cout<<"Base3 destructor called"<<endl;}
};
class Derived:public Base2,public Base1,public Base3
{
Base3 member3;
Base1 member1;
Base2 member2;
Base member;
public:
Derived(int i, int a,int b,int c,int d,int e,int f,int g)
:Base1(g,a),member2(e),member1(g,d),Base2(b),member3(f),Base3(c),member(i)
{cout<<"Derived constructor called "<<i<<endl;}
~Derived(void) {cout<<"Derived destructor called"<<endl;}
};
int main()
{
Derived objD(1,2,3,4,5,6,7,8);
return 0;
}
【案例7-5】解决“2-1”型多继承中二义性问题——多继承中同名隐藏与二义性
#include <iostream>
using namespace std;
class Base1
{
int b1;
public:
Base1(int i) {b1=i; cout<<"Base1 constructor called "<<endl; }
void disp() {cout<<"Base1: b1="<<b1<<endl;}
};
class Base2
{
int b2;
public:
Base2(int i) {b2=i; cout<<"Base2 constructor called "<<endl; }
void disp() {cout<<"Base2: b2="<<b2<<endl;}
};
class Derived:public Base2,public Base1
{
int d;
public:
Derived(int i,int a,int b):Base1(a),Base2(b)
{ d=i; cout<<"Derived constructor called "<<endl; }
void disp() {cout<<"Derived: d="<<d<<endl; }
};
int main()
{
Derived objD(1,2,3);
objD.disp(); //语句1:同名隐藏
objD.Base1::disp(); //语句2:使用作用域运算符::解决二义性问题
objD.Base2::disp(); //语句3:使用作用域运算符::解决二义性问题
return 0;
}
【案例7-6】应用虚基类解决多级继承中的二义性
#include <iostream>
using namespace std;
class Base
{
protected:
int b;
public:
Base(int i) {b=i; }
void disp() {cout<<"Base: b="<<b<<endl;}
};
class Base1:virtual public Base
{
int b1;
public:
Base1(int i,int j):Base(j) {b1=i; }
};
class Base2:virtual public Base
{
int b2;
public:
Base2(int i,int j):Base(j) {b2=i; }
};
class Derived:public Base2,public Base1
{
int d;
public:
Derived(int i,int j,int a,int b):Base(j),Base1(j,a),Base2(j,b)
{d=i; }
void disp() {cout<<"Derived: d="<<d<<endl; }
};
int main()
{
Derived objD(1,2,3,4);
objD.disp(); //语句1:同名隐藏
objD.Base::disp(); //语句2:通过虚基类解决了二义性问题
objD.Base1::disp(); //语句3:通过作用域标识符访问Base的disp()
objD.Base2::disp(); //语句4:通过作用域标识符访问Base的disp()
return 0;
}
【案例7-7】包含虚基类和非虚基类多级继承和构造函数和析构函数
#include <iostream>
using namespace std;
class Base1
{
public:
Base1(int i) {cout<<"Base1 constructor called "<<i<<endl; }
~Base1(void) {cout<<"Base1 destructor called"<<endl; }
};
class Base2
{
public:
Base2(int i) {cout<<"Base2 constructor called "<<i<<endl; }
~Base2(void) {cout<<"Base2 destructor called"<<endl; }
};
class ExtBase1:virtual public Base1,public Base2 //语句1
{
public:
ExtBase1(int i,int j):Base1(i),Base2(j) //语句2:构造函数向基类传递参数
{ cout<<"ExtBase1 constructor called "<<i<<endl; }
~ExtBase1(void)
{ cout<<"ExtBase1 destructor called"<<endl; }
};
class ExtBase2:public Base2,virtual public Base1 //语句3:扩展基类
{
public:
ExtBase2(int i,int j):Base2(j),Base1(i) //语句4:构造函数向基类传递参数
{ cout<<"ExtBase2 constructor called "<<i<<endl; }
~ExtBase2(void) {cout<<"ExtBase2 destructor called"<<endl; }
};
class Derived:public ExtBase2,public ExtBase1 //语句5:派生类
{
public:
Derived(int i, int a,int b,int c)
:ExtBase1(i,a),ExtBase2(i,b),Base1(c) //语句6:构造函数向直接基类和虚基类传递参数
{ cout<<"Derived constructor called "<<i<<endl; }
~Derived(void)
{ cout<<"Derived destructor called"<<endl; }
};
int main()
{
Derived objD(1,2,3,4); //语句7:创建派生类对象
return 0;
}
【案例8-1】编写矩形类——重载成员函数
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
class CRect
{
long left; long top;
long right; long bottom;
public:
CRect(int l=1, int t=2, int r=3, int b=4);
void SetRect(int x1, int y1, int x2, int y2); //重载的成员函数
void SetRect(const CRect& r) ; //重载的成员函数
void Disp();
};
void CRect::Disp() //成员函数显示自身的数据
{
cout<<"left="<<left<<"; top="<<top<<"; right="<<right<<"; bottom="<<bottom;
}
CRect::CRect(int l, int t, int r, int b) //带参构造函数调用自身的成员函数
{
SetRect(l,t,r,b);
}
void CRect::SetRect(const CRect& r) //重载设置矩形成员函数
{
left =r.left;
top = r.top;
right = r.right;
bottom = r.bottom;
}
void CRect::SetRect(int l, int t, int right, int bottom) //重载设置矩形成员函数
{
left = l;
top = t;
this->right = right;
this->bottom = bottom;
}
int main()
{
CRect r,s; //调用构造函数CRect(1, 2, 3, 4)定义对象
r.Disp(); //r对象显示数据
r.SetRect(5,6,7,8);
s.SetRect(r); //调用重载的成员函数
s.Disp(); //显示s对象数据
return 0;
}
【案例8-2】电话号码类PhoneNumber——重载流提取与流插入运算符
#include <iostream>
#include <iomanip>
using namespace std;
class PhoneNumber
{
//重载流插入操作符,如果需要使用cout << somePhoneNumber;则不能重载为成员函数
friend ostream &operator<<( ostream &output, const PhoneNumber &num )
{
output << "(" << num.areaCode << ") "<< num.exchange << "-" << num.line;
return output;
}
//重载流插入操作符,如果使用cin >> somePhoneNumber;则不能重载为成员函数
friend istream &operator>>( istream &input, PhoneNumber &num )
{
input.ignore(); input >> setw( 4 ) >> num.areaCode;
input.ignore( 2 ); input >> setw( 4 ) >> num.exchange;
input.ignore(); input >> setw( 5 ) >> num.line;
return input;
}
private:
char areaCode[4],exchange[4],line[5];
};
int main()
{
PhoneNumber phone; //创建对象phone
cout << "Enter phone number in the form (123) 456-7890: ";
cin >> phone; //语句1:使用流提取运算符
cout << "The phone number entered was: "<< phone << endl; //语句2:使用流插入运算符
return 0;
}
【案例8-3】编写词汇类Words——重载下标操作符[]
#include <iostream>
#include <string>
using namespace std;
class Words
{
char *str;
public:
Words (char *s) {str=new char[strlen (s) +1] ; strcpy(str, s) ; }
void disp() {cout << str << endl;}
char &operator[] (int i) { return *(str+i);} //语句1:返回str[i]
};
int main()
{
char *s="china";
Words word(s) ;
word.disp () ;
int n=strlen(s) ;
while (n>=0)
{
word [n-1] =word [n-1 ] -32 ; //语句2:字母转化为大写
n--;
}
word.disp () ;
return 0;
}
【案例8-4】显示和隐式调用虚函数
#include <iostream>
using namespace std;
class Base
{
public:
virtual void fun(); //fun()是虚函数
private:
long m_nx;
};
void Base::fun()
{
cout<<"Base="<<sizeof(Base)<<endl;
}
class Derived: public Base
{
long m_ny;
void fun(); //派生类的覆盖版本是私有的
};
void Derived::fun()
{
cout<<"Derived="<<sizeof(Derived)<<endl;
}
void Showv(Base objx)
{
objx.fun(); //对象形参调用虚函数,静态绑定
}
void Show(Base* pBase)
{
pBase->fun(); //指针形参隐式调用虚函数,动态绑定
}
void Show(Base& r)
{
r.Base::fun(); //语句1:引用形参显式调用基类虚函数,静态绑定
}
void main()
{
Base* pobjx=new Base();
Derived objy;
int k;
cout<<"Please input k:";
cin>>k;
if(k==1)
{
Show(pobjx);
Show(&objy);
} // k=1调用指针形参的Show版本
else // k不等于1调用引用形参Show版本
{
Show(*pobjx);
Show(objy);
}
Showv(objy); // Showv调用中实参是派生类对象objy,形参是基类对象objx
}
【案例8-5】设计形状类Shape——通过两级抽象基类实现统一接口
#include <cmath>
#include <iostream>
using namespace std;
const double PI=3.14159265358979;
class Shape //声明抽象基类
{
public:
virtual void Disp() = 0;
virtual float area() = 0;
};
class TwoDShape : public Shape //抽象派生类TwoDShape
{
public:
virtual float perimeter() = 0;
};
class ThreeDShape : public Shape //抽象派生类ThreeDShape
{
public:
virtual float volume() = 0;
};
class Circle : public TwoDShape
{
public:
Circle(float r) : radius(r) { }
void Disp() { cout << "Shape is a circle.\n"; }
float perimeter() { return 2*PI*radius; }
float area() { return PI*radius*radius; }
private:
float radius;
};
class Rectangle : public TwoDShape
{
public:
Rectangle(float l, float w) : length(l),width(w) { }
void Disp() { cout << "Shape is a Rectangle.\n"; }
float perimeter() { return 2*(length+width); }
float area() { return length*width; }
private:
float length,width;
};
class Cone : public ThreeDShape
{
public:
Cone(float r, float h) : radius(r), height(h) { }
void Disp() { cout << "Shape is a Cone.\n"; }
float area(){return PI*radius*(radius+sqrt(radius*radius + height*height));}
float volume() { return PI*radius*radius*height/3; }
private:
float radius, height;
};
class Box : public ThreeDShape
{
public:
Box(float l, float w,float h) : length(l),width(w), height(h) { }
void Disp() { cout << "Shape is a Box.\n"; }
float area(){return 2*(length*width+length*height+width*height);}
float volume() { return length*width*height; }
private:
float length,width, height;
};
int main()
{
Shape *ShapePtr=0;
Circle c(2);
ShapePtr=&c;
ShapePtr->Disp();
//cout<<ShapePtr->perimeter(); //语句1:编译错误
cout<<ShapePtr->area()<<"\n";
Rectangle r(2,3);
ShapePtr=&r;
ShapePtr->Disp();
//cout<<ShapePtr->perimeter(); //语句2:编译错误
cout<<ShapePtr->area()<<"\n";
Cone co(1, 2);
ShapePtr=&co;
ShapePtr->Disp();
//cout<<ShapePtr->perimeter(); //语句3:编译错误
cout<<ShapePtr->area()<<"\n";
Box b(1, 2,3);
ShapePtr=&b;
ShapePtr->Disp();
//cout<<ShapePtr->perimeter(); //语句4:编译错误
cout<<ShapePtr->area()<<"\n";
return 0;
}
说明:通过基类的指针是不能访问派生类独有的成员函数,若需要访问这些函数,需要在基类中声明同名函数,并声明为virtual类型
C++简单程序常见错误
【2-1】正确输出1~10的和——书写错误
#include<iostream>
using namespace std;
void main(void)
{
int i,sum;
sum=0;
for(i=1;i<=10;i++); //多余的分号,导致错误的输出
sum=sum+i;
cout<<"sum="<<sum<<endl;
}
【2-2】求1+1/3+1/5+1/7+.....+1/n,n由键盘输入得到——数据类型的转换
#include<iostream>
using namespace std;
void main(void)
{
int i,n;
double sum,item;
cout<<"enter n:";
cin>>n;
sum=0;
for(i=1;i<=n;i++);
item=1/(2*i-1); //item是double,分子应该为1.0,sum才会正确
sum=sum+item;
cout<<"sum="<<sum<<endl;
}
【2-3】计算图形面积——书写和格式错误
#include<iostream>
using namespace std;
const float PI=3.1416;
void main()
{
int iType;
float radius,a,b,area;
cout<<"图形的类型为?(1-圆形 2-长方形 3-正方形):";
cin>>iType;
switch(iType)
{
case1: //编译不报错,但无结果,应该在case与1之间有空格
cout<<"圆的半径为:";
cin>>radius;
area=PI*radius*radius;
cout<<"面积为:"<<area<<endl;
break;
case2: //编译不报错,但无结果,应该在case与2之间有空格
cout<<"矩形的长为:";
cin>>a;
cout<<"矩形的宽为:";
cin>>b;
area=a*b;
cout<<"面积为:"<<area<<endl;
break;
case3: //编译不报错,但无结果,应该在case与3之间有空格
cout<<"正方形的边长为:";
cin>>a;
area=a*a;
cout<<"面积为:"<<area<<endl;
break;
default:
cout<<"不是合法的输入值!"<<endl;
}
}
【2-4】正确输出“50000”——整型数值溢出
#include <iostream>
using namespace std;
int main()
{
short int i; // signed short 类型整数
short unsigned int j; // unsigned short类型整数
j = 50000; i = j; //将unsigned short类型整数赋值给signed short类型变量
cout <<" The short int is:"<< i <<endl; //整型数值溢出
cout <<" The short unsigned int is:"<< j<<endl;
return 0;
}
【2-5】整型和浮点型数值溢出问题
#include <iostream>
using namespace std;
int main()
{
int m=1000;
cout << "m = " << m << endl;
m *= 1000000000;
cout << "m = " << m << endl; //语句1:整型溢出
float n=1000.0;
cout << "n = " << n << endl;
n *= n; n *= n; n *= n; n *= n;
cout << "n = " << n << endl; //语句2:浮点型溢出
return 0;
}
【2-6】判断2个有理数是否相同——四舍五入带来的逻辑错误
#include <iostream>
using namespace std;
int main()
{
double x = 10/7.0; cout << "x = " << x << endl;
if (x == 1.142857142857) cout << "x == 10/7.0\n"; //存在四舍五入带来的逻辑错误
else cout << "x does not equal 10/7.0\n";
double z = 7.0*x - 10; cout << "z = " << z << endl;
if (z == 0) cout << "z == 0.\n"; //存在四舍五入带来的逻辑错误
else cout << "z does not equal 0.\n";
return 0;
}
【2-7】布尔表达式引发的逻辑错误
#include <iostream>
using namespace std;
int main()
{
int i1, i2, i3;
cout << "Enter three integers: "; cin >> i1 >> i2 >> i3;
if (i1 >= i2 >= i3)
cout << "max = " << i1<<endl; //布尔表达式引起逻辑错误
return 0;
}
【2-8】“赋值运算符”与“相等关系运算符”的混淆
#include <iostream>
using namespace std;
int main()
{
int n;
cout << "Enter an integer: "; cin >> n;
if (n = 20)
cout << n << " = 20" << endl; //语句1:使用的是赋值运算符
else
cout << n << " != 20" << endl;
return 0;
}
【2-9】中止无限循环——break语句
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
while (1) //死循环
{
cout<<"Running the loop, until you hit a key.\n";
if(kbhit())
break; //检查是否有按键按下
}
cout<<"\n Loop is over.\n";
return 0;
}
第二章 函数常见错误
【3-1】自动类型转换导致重载函数的二义性
#include <iostream>
using namespace std;
float myfunc(float i);
double myfunc(double i);
int main()
{
cout << myfunc(10.1) << " "; //不会出现二义性,默认调用函数 myfunc(double)
cout << myfunc(10); //错误!出现二义性
return 0;
}
float myfunc(float i)
{
return i;
}
double myfunc(double i) {
return -i;
}
【3-2】默认参数导致重载函数的二义性
#include <iostream>
using namespace std;
int myfunc(int i);
int myfunc(int i, int j=1);
int main()
{
cout << myfunc(4, 5) << " "; // 不存在二义性
cout << myfunc(10); // 错误,存在二义性!
return 0;
}
int myfunc(int i) {
return i;
}
int myfunc(int i, int j)
{
return i*j;
}
第四章 类与对象常见错误
【4-1】错误的由来——前向引用声明的局限
#include <iostream>
using namespace std;
class Second; //前向引用声明
class First
{
Second *x;
public:
void callSecond()
{x->funFirst();} //错误:在Second类定义之前使用了该类的函数
};
class Second
{
First *y;
public:
void funFirst()
{cout<<"This is calling Second"<<endl;}
};
int main()
{
First a;
a.callSecond();
return 0;
}
解决方法:将成员函数的定义void callSecond() {x->funFirst();} 移到类Second的声明之后
第五章 C++程序的结构常见错误
【5-1】嵌套作用域中的局部变量
#include <iostream>
using namespace std;
int main()
{
int x = 10; //x 对于整个程序是可见的
if(x == 10)
{
int y = 20;
cout << "x + y is " << x + y << "\n";
}
//y = 100; //错误! y 在此是不可见的
return 0;
}
【5-2】有理分数的输出——类作用域变量
#include <iostream>
using namespace std;
class ZRF
{
public:
int den; //公有成员具有局部作用域
ZRF(int n=0, int d=1) : num(n), den(d) { } //带默认参数值的构造函数
void disp() { cout << num << '/' << den; } //公有函数具有局部作用域
private:
int num;
};
int main()
{
ZRF z(20);
cout << "z = "; z.disp(); //在类外访问类的公有函数
cout << "\nz = "; z.den=50; z.disp(); //在类外访问类的公有成员
cout << "\nz = "; z.disp();
//z.num=10; //错误:在类外不能访问类的私有成员
return 0;
}
【5-3】使用符号常量
#include <iostream>
using namespace std;
int main()
{
const char BEEP = '\b'; //定义字符常量
const int MAXINT = 2147483647; //定义整型常量
const float KM_PER_MI = 1.60934; //定义浮点型常量
const double PI = 3.14159265358979323846; //定义双精度型常量
//PI=3.1415926; //错误!不能赋值
cout<<"The MAXINT is:"<<MAXINT<<endl;
cout<<"The KM_PER_MI is:"<<KM_PER_MI<<endl;
cout<<"The PI is:"<<PI<<endl;
cout<<"The BEEP is:"<<BEEP<<endl;
return 0;
}
【5-4】错误的调用——常量对象
#include <iostream>
using namespace std;
class ZRF
{
public:
ZRF(int i) { num=i; cout<<"ZRF is constructed\n";}
~ZRF() {cout<<"ZRF is destructed\n";}
void disp() { cout<<"The value of num is:"<<num<<endl;}
int num;
};
int main()
{
const ZRF x(10); // 声明常对象
x.num=20; //错误1
x.disp(); //错误2
return 0;
}
说明:常对象的数据成员值在对象的整个生存期间内不能被改变,也就是说,常对象必须进行初始化,而且不能被更新。
第六章 数组、指针与字符串常见错误
【6-1】计算数组元素个数——数组的部分初始化
#include <iostream>
using namespace std;
int main()
{
float Array[5] = { 10, 20, 30 }; //部分初始化数组
//float Array[2] = { 10, 20, 30 }; //错误
int size = sizeof(Array)/sizeof(float); //求数组实际分配大小
for (int i=0; i<size; i++)
cout << "Array[" << i << "] = " << Array[i] << endl;
return 0;
}
【6-2】垃圾数据的由来——数据元素下标越界
#include <iostream>
using namespace std;
int main()
{
const int SIZE=4; //定义数组大小
float Array[SIZE] = { 10, 20, 30, 40 };
float f1=12.3, f2=45.6, f3=78.9;
for (int i=0; i<7; i++) //下标超出范围!
cout << "Array[" << i << "] = " << Array[i] << endl;
return 0;
}
【6-3】运行错误的由来——数组元素下标越界的严重副作用
#include <iostream>
using namespace std;
int main()
{
float Array[] = { 10, 20, 30 }; //语句1:声明三个元素的数组
cout << "Array[3] = " << Array[3] << endl;
Array[3] = 80.8f; //语句2:错误:下标越界!
cout << "Array[3] = " << Array[3] << endl;
return 0;
}
【6-4】为变量另起名字——引用的初始化
#include <iostream>
using namespace std;
int main()
{
int n=44;
//int& rn=55; //错误:55不是一个变量!
int& rn=n; //rn 是变量 n的别名
cout << "The value of n is: " << n << ", The value rn is: " << rn << endl;
--n;
cout << "The value of n is: " << n << ", The value rn is: " << rn << endl;
rn *= 3;
cout << "The value of n is: " << n << ", The value rn is: " << rn << endl;
return 0;
}
【6-5】不可识别的“100.20”——指针的类型匹配
#include <iostream>
using namespace std;
int main()
{
double x, y; int *p;
x = 100.20;
p = (int *) &x; //将类型double * 强制转换为int *
y = *p;
cout << y; //此语句将不能得到预期的结果。
return 0;
}
说明:将变量x(double类型)的地址赋给了整型指针p,当所指向的值赋给y时,y仅仅接收4个字节数的数据,而不是double类型所要求的8个字节,所以输出结果并非预想的数值。
【6-6】区分“指向常量的指针”和“指针类型的常量”
#include <iostream>
using namespace std;
int main()
{
int i=10,j=20;
const int* pi=&i; //指向常量的指针
//*pi=20; //错误1:不能通过pi改变所指向变量的值
cout<<"pi="<<pi<<"*pi="<<*pi<<endl;
int* const pj=&j; //指针类型的常量
//pj=pi; //错误2:不能修改pj的值
cout<<"pj="<<pj<<"*pj="<<*pj<<endl;
return 0;
}
【6-7】为变量动态分配内存
#include<iostream>
using namespace std;
int main()
{
int *pi;
//pi=3.5; //语句1:错误,没有内存单元被分配给*pi
int i=3;
pi=&i; //语句2:通过将变量的地址赋给指针变量进行初始化
cout<<"The address is:"<<pi<<", and the value is:"<<*pi<<endl;
float *pf;
pf=new float; //语句3:分配一个float的内存单元
*pf=3.6f; //语句4:正确初始化,*qf已经被分配了内存空间
cout<<"The address is:"<<pf<<", and the value is:"<<*pf<<endl;
double *pd;
pd=new double(3.7); //语句5:分配一个double的内存单元并初始化
cout<<"The address is:"<<pd<<", and the value is:"<<*pd<<endl;
return 0;
}
第七章 继承与派生常见错误
【7-1】私有继承中成员的访问
#include <iostream>
using namespace std;
class Base
{
int x,y; //私有数据成员
protected:
int a,b; //保护数据成员
public:
int m,n; //公有数据成员
void SetX(int X) {x=X;} //为私有数据成员设置接口
void SetY(int Y) {y=Y;} //为私有数据成员设置接口
int GetX(){return x;} //为私有数据成员设置接口
int GetY(){return y;} //为私有数据成员设置接口
};
class Derived:private Base
{
void SetXY(int X, int Y) {SetX(X); SetY(Y);} //语句1:使用基类接口函数设置数据
void SetAB(int A, int B) {a=A; b=B;} //派生类可以直接访问基类的保护数据
void SetMN(int M, int N) {m=M; n=N;} //派生类可以直接访问基类的公有数据
int GetSumXY() {return (GetX()+GetY());} //语句2:使用基类接口函数提取数据
int GetSumAB() {return (a+b);} //派生类可以直接访问基类的保护数据
int GetSumMN() {return (m+n);} //派生类可以直接访问基类的公有数据
};
int main()
{
Derived objD;
objD.SetXY(1,2);
objD.SetAB(10,20);
objD.SetMN(100,200);
cout<<"X+Y="<<objD.x+objD.y<<endl; //错误,派生类对象不能直接访问私有数据
cout<<"A+B="<<objD.a+objD.b<<endl; //错误,派生类对象不能直接访问保护数据
cout<<"M+N="<<objD.m+objD.n<<endl; //错误,派生类对象不能直接访问公有数据
return 0;
}
【7-2】多次继承一个基类的错误
#include <iostream>
using namespace std;
class Base
{
protected:
int b;
public:
Base(int i) {b=i; cout<<"Base constructor called "<<endl; }
void disp() {cout<<"Base: b="<<b<<endl;}
};
class ExtBase:public Base,public Base //语句1:错误,不能从同一个基类继承一次以上
{
int eb;
public:
ExtBase(int i,int j):Base(j){eb=i; cout<<"ExtBase constructor called "<<endl; }
};
class Derived:public ExtBase,public Base //语句2:错误,不能同时使用基类和扩展基类
{
int d;
public:
Derived(int i,int a,int b):ExtBase(i,a),Base(b)
{d=i; cout<<"Derived constructor called "<<endl;}
void disp() {cout<<"Derived: d="<<d<<endl;}
};
int main()
{
Derived objD(1,2,3);
objD.disp();
objD.Base::disp();
objD.ExtBase::disp();
return 0;
}
第八章 多态性常见错误
【8-1】点类Point和圆类Circle——通过虚函数实现基类调用派生类成员函数
#include <iostream>
#include <iomanip>
using namespace std;
class Point
{
public:
Point( int xValue = 0, int yValue = 0 ) : x( xValue ), y( yValue ){}; //默认构造函数
void setX ( int xValue ) { x = xValue; } //设置x 坐标
int getX() const { return x;} //获取x坐标
void setY( int yValue ) { y = yValue; } //设置y 坐标
int getY() const { return y;} //获取y坐标
//void Disp() const {cout << '[' << getX() << ", " << getY() << ']';}; //不正确,应定义为虚函数
virtual void Disp() const {cout << '[' << getX() << ", " << getY() << ']';};
private:
int x,y; // x,y 坐标
};
class Circle : public Point //圆类
{
public:
Circle( int xValue= 0, int yValue= 0, double radiusValue= 0.0) : Point( xValue, yValue )
{ setRadius( radiusValue );}
void setRadius( double radiusValue ) //设置半径
{radius = ( radiusValue < 0.0 ? 0.0 : radiusValue );}
double getRadius() const{ return radius;} //获取半径
double getDiameter() const{ return 2 * getRadius();} //获取直径
double getCircumference() const{ return 3.14159 * getDiameter();} //获取周长
double getArea() const{ return 3.14159 * getRadius() * getRadius();} //获取面积
void Disp() const //输出圆对象
{cout << "center = "; Point::Disp(); //调用Point类的Disp函数
cout << "; radius = " << getRadius();
}
private:
double radius; // 圆半径
};
int main()
{
Point point( 30, 50 );
Point *pointPtr = 0; //基类指针
Circle circle( 120, 89, 2.7 );
Circle *circlePtr = 0; //派生类指针
pointPtr = &point; //将基类对象赋给基类指针
pointPtr->Disp(); //调用基类成员函数
cout << endl; pointPtr = &circle; //将派生类对象赋给基类指针
pointPtr->Disp(); //调用的是基类成员函数(不是派生类成员函数)
return 0;
}
【8-2】点类Point和圆类Circle——通过基类的指针不能调用派生类非虚函数
#include <iostream>
#include <iomanip>
using namespace std;
class Point
{
public:
Point( int xValue = 0, int yValue = 0 ) : x( xValue ), y( yValue ){}; //默认构造函数
void setX ( int xValue ) { x = xValue; } //设置x 坐标
int getX() const { return x;} //获取x坐标
void setY( int yValue ) { y = yValue; } //设置y 坐标
int getY() const { return y;} //获取y坐标
void Disp() const {cout << '[' << getX() << ", " << getY() << ']';};
private:
int x,y; // x,y 坐标
};
class Circle : public Point //圆类
{
public:
Circle( int xValue= 0, int yValue= 0, double radiusValue= 0.0) : Point( xValue, yValue )
{ setRadius( radiusValue );}
void setRadius( double radiusValue ) //设置半径
{ radius = ( radiusValue < 0.0 ? 0.0 : radiusValue );}
double getRadius() const{ return radius;} //获取半径
double getDiameter() const{ return 2 * getRadius();} //获取直径
double getCircumference() const{ return 3.14159 * getDiameter();} //获取周长
double getArea() const{ return 3.14159 * getRadius() * getRadius();} //获取面积
void Disp() const //输出圆对象
{ cout << "center = "; Point::Disp(); //调用Point类的Disp函数
cout << "; radius = " << getRadius();
}
private:
double radius; // 圆半径
};
int main()
{
Point point( 30, 50 );
Point *pointPtr = 0; // 基类指针
Circle circle( 120, 89, 2.7 );
Circle *circlePtr = 0; //派生类指针
pointPtr = &circle;
int x=pointPtr->getX();
int y=pointPtr->getY();
double r=pointPtr->getRadius(); //错误
double d=pointPtr->getDiameter(); //错误
cout << endl;
return 0;
}
第一、二章优秀习作
1.输入一个4位无符号整数,凡需输出这4位数。例如输入上的4位数为1234,则输出的4位数是4321.
#include <iostream>
using namespace std;
void main()
{
int n,right_digit;
cout<<"enter the number(1000~9999):";
cin>>n;
cout<<"The number in reverse order is ";
do
{
right_digit=n%10;
cout<<right_digit;
n/=10;
}
while(n!=0);
cout<<endl;
}
2.编写一个程序,寻找用户输入的几个整数中的最小值。假定用户输入的第一个数值指定后面要输入的数值个数。例如,当用户输入数列为20,15,300,9,700时,程序应该能找到最小数9。
#include<iostream>
using namespace std;
void main()
{
int i,n,a,min;
cout<<"请输入数目:";
cin>>n;
cout<<"请输入一个整数:";
cin>>a;
min=a;
for(i=2;i<=n;i++)
{
cout<<"请输入一个整数:";
cin>>a;
if(min>a)
min=a;
}
cout<<"最小数为:"<<min;
}
3.有一个分数序列2/1、3/2、5/3、8/5……..求其前n项之和。
#include <iostream>
using namespace std;
void main()
{
int i=1,j=2,s=1,n;
float sum=0,x;
cout<<"项数为";
cin>>n;
while(s<=n)
{
x=(float)j/i;
sum+=x;
j=i+j;
i=j-i;
s++;
}
cout<<"总和为:"<<sum<<endl;
}
4.求a+aa+aaa+aaaa+ ……+aaaa…aaa(n个),其中a为1~9值的整数。例如,当a=1、n=3时,求1+11+111之和;当a=5、n=7时,求5+55+555+5555+55555+555555+5555555之和。
#include <iostream>
#include <cmath>
using namespace std;
void main ()
{
int a,n,i,sum(0),k;
cout<<"请输入a和n的值:";
cin>>a>>n;
for(i=1;i<=n;i++)
sum+=a*(n-i)*pow(10,i)+a;
cout<<"当a="<<a<<",n="<<n<<"时,原式值为"<<sum<<endl;
}
5.猜幻数游戏。由系统随机给出一个数字(即幻数),游戏者去猜,如果猜对,则打印成功提示;否则,打印出错提示,并提示游戏者悬着下一步动作,最多可以猜5次。
#include <iostream>
#include <cstdlib>
using namespace std;
void main()
{
int count=0,MagNum, GueNum;
MagNum = rand(); //产生随机数
while (count<5)
{
cout << "Enter the Guess number: ";
cin >> GueNum;
if (GueNum == MagNum)
{
cout << "猜对了!"<<endl;
break;
}
else
{
if(GueNum > MagNum)
cout <<"猜的数太大了.\n";
else
cout << "猜的数太小了.\n";
}
count++;
}
cout << "超过了5次,不能猜了!"<<endl;
}
6.编写生日卡片的程序,使其能够输入和显示日期。
#include <iostream>
using namespace std;
struct birthday
{
char name[8];
int month;
int day;
};
void main()
{
birthday birthday;
cout<<"请输入个人信息:";
cin>>birthday.name>>birthday.month>>birthday.day;
cout<<birthday.name<<"的生日为:"<<birthday.month<<"月"<<birthday.day<<"日"<<endl;
cout<<"生日快乐!";