目录
本章小结
C++鼓励程序员在开发程序时使用多个文件.一种有效的组织策略是,使用头文件来定义用户类型,为操纵用户类型的函数提供函数原型:并将函数定义放在一仁个独立的源代码文件中.头文件和源代码文件一起定义和实现了用户定义的类型及其使用方式。最后;将main()和其他使用这些函数的函数放在第三个文件中。
C++的存储方案决定了变量保留在内存中的时间(储存持续性)以及程序的哪一部分可以访问它(作用域和链接性)。自动变量是在代码块(如函数体或函数体中的代码块)中定义的变量,仅当程序执行到包含定义的代码块时,它们才存在,并且可见。自动变量可以通过使用存储类型说明符register或根本不使用说明符来声明,没有使用说明符时,变量将默认为自动的。reglster说明符提示编译器,该变量的使用频率很高,但C++11摒弃了这种用法。
静态变量在整个程序执行期间都存在。对于在函数外面定义的变量,其所属文件中位于该变量的定义后面的所有函数都可以使用它(文件作用域),并可在程序的其他文件中使用(外部链接性)。另一个文件要使用这种变量,必须使用extern关键字来声明它。对于文件间共享们变量,应在一个文件中包含其定义声明(无需使用extern,但如果同时进行初始化,也可使用它),并在其 他文件中包含引用声明(使用extern且不初始化)。在函数的外面使用关键字static定义的变量的作用域为整个文件.但是不能用于其他文件(内部链接性)。在代码块中使用关键字static定义的变量被限制在该代码块内(局部作用域、无链接性),但在整个程序执行期间.它都一直存在并且保持原值。
在默认情况下,C++函数的链接性为外部,因此可在文件间共享:但使用关键字static限定的函数的链接性为内部的,被限制在定义它的文件中。
动态内存分配和释放是使用new和delete进行的,它使用自由存储区或堆来存储数据。调用new占用内存,而调用delete释放内存。程序使用指针来跟踪这些内存单元。
名称空间允许定义一个可在其中声明标识符的命名区域。这样做的目的是减少名称冲突,尤其当程序非常大,并使用多个厂商的代码时.可以通过使用作用域解析运算符、using声明或using编译指令,来使名称空问中的标识符可用。
程序清单
头文件和源代码文件一起编译
9.1头文件
//coordin.h -- structure templates and function prototypes
//structure templates
#ifndef COORDIN_H_
#define COORDIN_H_
struct polar
{
double distance;
double angle;
};
struct rect
{
double x;
double y;
};
//prototypes
polar rect_to_polar(rect xypos);
void show_polar(polar dapos);
#endif // !COORDIN_H_
9.2主函数源代码文件
// file1.cpp -- example of a three-file program
#include "stdafx.h"
#include "coordin.h"//structure templates, function prototypes
#include<iostream>
using namespace std;
int main()
{
rect rplace;
polar pplace;
cout << "Enter the x and y values: ";
while (cin >> rplace.x >> rplace.y)
{
pplace = rect_to_polar(rplace);
show_polar(pplace);
cout << "Next two numbers (q to quit): ";
}
cout << "Bye!\n";
return 0;
}
9.3函数源代码文件
// file2.cpp -- contains functions called in file1.cpp
#include "stdafx.h"
#include "coordin.h"
#include<iostream>
#include<cmath>
using namespace std;
polar rect_to_polar(rect xypos)
{
polar answer;
answer.distance = sqrt(xypos.x*xypos.x + xypos.y*xypos.y);
answer.angle = atan2(xypos.y, xypos.x);
return answer;
}
//show polar coordinates, converting angle to degrees
void show_polar(polar dapos)
{
const double Rad_to_deg = 57.29577951;
cout << "distance = " << dapos.distance;
cout << "angle = " << dapos.angle*Rad_to_deg << " degrees\n";
}
9.4 auto变量的作用域
//autoscp.cpp -- illustrating scope of automatic variables
#include "stdafx.h"
#include<iostream>
void oil(int x);
int main()
{
using namespace std;
int texas = 31;
int year = 2011;
cout << "In main(), texas = " << texas << ", &texas = " << &texas << endl;
cout << "In main(), year = " << year << ", &year = " << &year << endl;
oil(texas);
cout << "In main(), texas = " << texas << ", &texas = " << &texas << endl;
cout << "In main(), year = " << year << ", &year = " << &year << endl;
return 0;
}
void oil(int x)
{
using namespace std;
int texas = 5;
cout << "In oil(), texas = " << texas << ", &texas = " << &texas << endl;
cout << "In oil(), x = " << x << ", &x = " << &x << endl;
{
int texas = 113;
cout << "In block, texas = " << texas << ", &texas = " << &texas << endl;
cout << "In block, x = " << x << ", &x = " << &x << endl;
}
cout << "Post-block texas = " << texas << ", &texas = " << &texas << endl;
}
extern变量的静态持续性及外部链接性
9.5 主函数文件
//external.cpp -- external veriables
//compile with support.cpp
#include "stdafx.h"
#include<iostream>
using namespace std;
double warming = 0.3;
void update(double dt);
void local();
int main()
{
cout << "Global warming is " << warming << " degrees.\n";
update(0.1); //call function to change warming
cout << "Global warming is " << warming << " degrees.\n";
local(); //call function with local warming
cout << "Global warming is " << warming << " degrees.\n";
return 0;
}
9.6 函数定义文件
//support.cpp -- use external variable
//compile with external.cpp
#include "stdafx.h"
#include<iostream>
extern double warming; //use warming from anotherf ile
void update(double dt);
void local();
using namespace std;
void update(double dt)//modifies global variable
{
extern double warming;//optional redeclaration
warming += dt;//uses global warming
cout << "Updating global warming to " << warming;
cout << " degrees.\n";
}
void local() //uses local varicale
{
double warming = 0.8;//new variable hides external one
cout << "Local warming = " << warming << " degrees.\n";
//Access global variable with the scope resolution operator
cout << "But global warming = " << ::warming << " degrees.\n";
}
static变量的静态持续性及内部链接性
9.7 主函数
/twofile1.cpp -- wariables with external and internal linkage
#include "stdafx.h"
#include<iostream>
int tom = 3;
int dick = 30;
static int harry = 300;
void remote_access();
int main()
{
using namespace std;
cout << "main() reports the following address:\n"
<< &tom << " = &tom, "
<< &dick << " = &dick, "
<< &harry << " = &harry\n";
remote_access();
return 0;
}
9.8 函数定义文件
//twofile2.cpp -- variables with internal and external linkage
#include "stdafx.h"
#include<iostream>
extern int tom;
static int dick = 10;
int harry = 200;
void remote_access()
{
using namespace std;
cout << "remote_access() reports the following addresses:\n"
<< &tom << " = &tom, "
<< &dick << " = &dick, "
<< &harry << " = &harry\n";
}
9.9 静态储存持续性及无连接性
//static.cpp -- using a static local variable
#include "stdafx.h"
#include<iostream>
const int ArSize = 10;
void strcount(const char * str);
int main()
{
using namespace std;
char input[ArSize];
char next;
cout << "Enter a line:\n";
cin.get(input, ArSize);
while (cin)
{
cin.get(next);
while (next != '\n')
cin.get(next);
strcount(input);
cout << "Enter next line (empty line to quit):\n";
cin.get(input, ArSize);
}
cout << "Bye\n";
return 0;
}
void strcount(const char * str)
{
using namespace std;
static int total = 0;
int count = 0;
cout << "\"" << str << "\" contains ";
while (*str++)
count++;
total += count;
cout << count << " character\n" << total << " characters total\n";
}
9.10 new运算符
//newplace.cpp -- using placement new
#include "stdafx.h"
#include<iostream>
#include<new>
const int BUF = 512;
const int N = 5;
char buffer[BUF];
int main()
{
using namespace std;
double *pd1, *pd2;
int i;
cout << "Calling new and placement new:\n";
pd1 = new double[N];
pd2 = new(buffer) double[N];
for (i = 0; i < N; i++)
pd2[i] = pd1[i] = 1000 + 20.0*i;
cout << "Memory addresses:\n" << " heap: " << pd1 << " static: " << (void *)buffer << endl;
cout << "Memory contents:\n";
for ( i = 0; i <N; i++)
{
cout << pd1[i] << " at " << &pd1[i] << "; ";
cout << pd2[i] << " at " << &pd2[i] << endl;
}
cout << "\nCalling new and placement new a second time:\n";
double *pd3, *pd4;
pd3 = new double[N];
pd4 = new(buffer)double[N];
for (i = 0; i < N; i++)
pd4[i] = pd3[i] = 1000 + 40.0*i;
cout << "Memory contents:\n";
for (i = 0; i < N; i++)
{
cout << pd3[i] << " at " << &pd3[i] << "; ";
cout << pd4[i] << " at " << &pd4[i] << endl;
}
cout << "\nCalling new and placement new a third time:\n";
delete[] pd1;
pd1 = new double[N];
pd2 = new(buffer + N * sizeof(double))double[N];
for (i = 0; i < N; i++)
pd2[i] = pd1[i] = 1000 + 60.0*i;
cout << "Memory contents:\n";
for (i = 0; i < N; i++)
{
cout << pd1[i] << " at " << &pd3[i] << "; ";
cout << pd2[i] << " at " << &pd4[i] << endl;
}
delete[] pd1;
delete[] pd3;
return 0;
}
名称空间
9.11 头文件
//namesp.h
#include<string>
//create the pers and debts namespaces
namespace pers
{
struct Person
{
std::string fname;
std::string lname;
};
void getPerson(Person &);
void showPerson(const Person &);
}
namespace debts
{
using namespace pers;
struct Debt
{
Person name;
double amount;
};
void getDebt(Debt &);
void showDebt(const Debt &);
double sumDebts(const Debt ad[], int n);
}
9.12 函数定义文件
//namesp.cpp
#include <iostream>
#include "namesp.h"
namespace pers
{
using std::cout;
using std::cin;
void getPerson(Person & rp)
{
cout << "Enter first name: ";
cin >> rp.fname;
cout << "Enter last name: ";
cin >> rp.lname;
}
void showPerson(const Person & rp)
{
cout << rp.lname << ", " << rp.fname;
}
}
namespace debts
{
void getDebt(Debt & rd)
{
getPerson(rd.name);
std::cout << "Enter debt: ";
std::cin >> rd.amount;
}
void showDebt(const Debt & rd)
{
showPerson(rd.name);
std::cout << ": $" << rd.amount << std::endl;
}
double sumDebts(const Debt ar[], int n)
{
double total = 0;
for (int i = 0; i < n; i++)
total + ar[i].amount;
return total;
}
}
9.13 主函数文件
//usenmsp.cpp -- using namespaces
#include "stdafx.h"
#include "namesp.h"
#include<iostream>
void other(void);
void another(void);
int main(void)
{
using debts::Debt;
using debts::showDebt;
Debt golf = { {"Benny","Goatsniff"},120.0 };
showDebt(golf);
other();
another();
return 0;
}
void other(void)
{
using namespace std;
using namespace debts;
Person dg = { "Doodles","Glister" };
showPerson(dg);
cout << endl;
Debt zippy[3];
int i;
for (i = 0; i < 3; i++)
getDebt(zippy[i]);
for (i = 0; i < 3; i++)
showDebt(zippy[i]);
cout << "\nTotal debt: $" << sumDebts(zippy, 3) << endl;
return;
}
void another(void)
{
using namespace pers;
Person collector = { "Milo","Rightshift" };
pers::showPerson(collector);
std::cout << std::endl;
}
课后编程习题答案
习题1
//golf.h
const int Len = 40;
struct golf
{
char fullname[Len];
int handicap;
};
void setgolf(golf & g, const char * name, int hc);
int setgolf(golf & g);
void handicap(golf & g, int hc);
void showgolf(const golf & g);
//golf.cpp
#include <iostream>
#include "golf.h"
using namespace std;
int setgolf(golf & g)
{
cout << "Enter the golfer's name: \n";
cin.get(g.fullname, Len);
if (g.fullname[0] == '\0')
return 0;
cout << "Enter the handicap for " << g.fullname << endl;
while (!(cin >> g.handicap))
{
cin.clear();
while (cin.get() != '\n')
continue;
cout << "Please enter an integer.\n";
} cin.get();
return 1;
}
void setgolf(golf &g, const char *name, int hc)
{
strncpy_s(g.fullname, name, Len);
g.handicap = hc;
}
void handicap(golf &g, int hc)
{
g.handicap = hc;
}
void showgolf(const golf &g)
{
cout << "Golfer: " << g.fullname << "\n";
cout << "Handicap: " << g.handicap << "\n\n";
}
//main.cpp
#include <iostream>
#include "golf.h"
const int Men = 5;
int main()
{
golf golfer[Men];
int i;
for (i = 0; i < Men; i++)
{
if (setgolf(golfer[i]) == 0)
break;
}
for (int j = 0; j < i; j++)
showgolf(golfer[j]);
golf ann;
setgolf(ann, "Ann Birdfree", 24);
showgolf(ann);
handicap(ann, 4);
showgolf(ann);
return 0;
}
习题2
#include <iostream>
#include <string>
using namespace std;
void strcount(const string);
int main()
{
string input;
cout << "Enter a line:\n";
getline(cin, input);
while (input != "")
{
strcount(input);
cout << "Enter next line (empty line to quit):\n";
getline(cin, input);
}
cout << "Bye\n";
return 0;
}
void strcount(const string str)
{
static int total = 0;
int count;
count = str.size();
total += count;
cout << count << " characters\n";
cout << total << " characters total\n";
}
习题3
#include <iostream>
#include <new>
#include <cstring>
using namespace std;
struct chaff
{
char dross[20];
int slag;
};
int main()
{
chaff * p = new chaff[2];
strcpy_s(p[0].dross, "Piffa like");
p[0].slag = 5;
strcpy_s(p[1].dross, "Fuck me so hard");
p[1].slag = 6;
for (int i = 0; i < 2; i++)
cout << p[i].dross << " " << p[i].slag << endl;
return 0;
}
习题4
//Sales.h
namespace SALES
{
const int QUARTERS = 4;
struct Sales
{
double sales[QUARTERS];
double average;
double max;
double min;
};
// copies the lesser of 4 or n items from the array ar to the sales member of s and computes and stores the average, maximum, and minimum values of the entered items; remaining elements of sales, if any, set to 0
void setSales(Sales & s, const double ar[], int n);
// gathers sales for 4 quarters interactively, stores them in the sales member of s and computes and stores the average, maximum, and minimum values
void setSales(Sales & s);
// display all information in structure s
void showSales(const Sales & s);
}
//Sales.cpp
#include <iostream>
#include "Sales.h"
namespace SALES
{
using std::cout;
using std::cin;
using std::endl;
static double calaverage(double arr[], unsigned arrSize)
{
double sum = 0;
for (int i = 0; i < arrSize; i++)
sum += arr[i];
return sum / arrSize;
}
static double calmax(double arr[], unsigned arrSize)
{
double max = arr[0];
for (int i = 1; i < arrSize; i++)
{
if (max < arr[i])
max = arr[i];
}
return max;
}
static double calmin(double arr[], unsigned arrSize)
{
double min = arr[0];
for (int i = 1; i < arrSize; i++)
{
if ( min > arr[i])
min = arr[i];
}
return min;
}
void setSales(Sales &s, const double ar[], int n)
{
unsigned times =n < QUARTERS ? (unsigned)n : QUARTERS;
for (int i = 0; i < times; i++)
s.sales[i] = ar[i];
for (int i = times; i < QUARTERS; i++)
s.sales[i] = 0;
s.average = calaverage(s.sales, times);
s.max = calmax(s.sales, times);
s.min = calmin(s.sales, times);
}
void setSales(Sales & s)
{
cout << "Enter 4 sales:\n";
for (int i = 0; i < QUARTERS; i++)
{
cout << "sales " << i + 1 << ": ";
cin >> s.sales[i];
}
s.average = calaverage(s.sales, QUARTERS);
s.max = calmax(s.sales, QUARTERS);
s.min = calmin(s.sales, QUARTERS);
}
void showSales(const Sales &s)
{
cout << "sales: ";
for (int i = 0; i < QUARTERS; i++)
cout << s.sales[i] << " ";
cout << endl;
cout << "average: " << s.average << endl;
cout << "max: " << s.max << endl;
cout << "min: " << s.min << endl;
}
}
//main.cpp
#include <iostream>
#include "Sale.h"
using namespace std;
int main()
{
using namespace SALES;
Sales A, B;
double h[4] = { 1.1, 2.2, 3.3, 4.4 };
setSales(A);
showSales(A);
setSales(B);
showSales(B);
return 0;
}