9.1 单独编译
Visual Studio中新建头文件和源代码
通过解决方案资源管理器,如图所示:
分成三部分的程序(直角坐标转换为极坐标)
头文件coordin.h
#ifndef __COORDIN_H__ // 如果没有被定义过
#define __COORDIN_H__
struct polar {
double distance;
double angle;
};
struct rect {
double x;
double y;
};
polar rect_to_polar(rect xypos);
void show_polar(polar dapos);
#endif // 如果被定义过了(啥也不做)
源代码file1(放置main函数,调用其他函数)
#include <iostream>
#include "coordin.h" // 尖括号表明去系统目录找,双引号表明去当前目录找
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!" << endl;
return 0;
}
源代码file2(其他函数的定义)
#include <iostream>
#include <cmath>
#include "coordin.h"
polar rect_to_polar(rect xypos) {
using namespace std;
polar answer;
answer.distance = sqrt(xypos.x * xypos.x + xypos.y * xypos.y);
answer.angle = atan2(xypos.y, xypos.x);
return answer;
}
void show_polar(polar dapos) {
using namespace std;
const double Rad_to_deg = 57.29577951;
cout << "distance = " << dapos.distance;
cout << ", angle = " << dapos.angle * Rad_to_deg;
cout << " degrees" << endl;
}
9.2 存储持续性、作用域和链接性
全局变量和局部变量
头文件support.h
#ifndef __SUPPORT_H__
#define __SUPPORT_H__
#include <iostream>
extern double warming; // 声明外部变量(不要赋值)
void update(double dt);
void local(void);
#endif
源代码external.cpp
#include <iostream>
#include "support.h"
using namespace std;
double warming = 0.3;
int main(){
cout << "Global warming is " << warming << endl;
update(0.1);
cout << "Global warming is " << warming << endl;
local();
return 0;
}
源代码support.cpp
#include "support.h"
using namespace std;
void update(double dt) {
warming += dt;
cout << "Updating global warming to " << warming << endl;
}
void local(void) {
double warming = 0.8; // 局部变量,只在local内部可见
cout << "Local warming is " << warming << endl;
// 作用域解析运算符(::),放在变量名前表示使用变量的全局版本
cout << "But global warming is " << ::warming << endl;
}
static限定符用于全局变量
源代码twofile1.cpp
#include <iostream>
using namespace std;
int tom = 3;
int dick = 30;
static int harry = 300; // 仅在twofile1.cpp可见
void remote_access(void);
int main() {
cout << "main() reports the following addresses: " << endl;
cout << "&tom = " << &tom << endl;
cout << "&dick = " << &dick << endl;
cout << "&harry= " << &harry << endl;
remote_access();
return 0;
}
源代码twofile2.cpp
#include <iostream>
using namespace std;
extern int tom; // 声明为外部变量(来自twofile1.cpp)
static int dick = 10; // 只在twofile2.cpp中可见
int harry = 200; // 新建一个全局变量
void remote_access(void) {
cout << "remote_access() reports the following addresses:" << endl;
cout << "&tom = " << &tom << endl;
cout << "&dick = " << &dick << endl;
cout << "&harry= " << &harry << endl;
}
static限定符用于局部变量(统计字符串的字符个数)
#include <iostream>
using namespace std;
const int ArSize = 10;
void strcount(const char * str);
int main(){
char input[ArSize];
char next;
cout << "Enter a line: " << endl;
cin.get(input, ArSize);
while (cin) {
cin.get(next);
// 如果输入的内容大于10个字符,则用cin.get全部消耗掉
while (next != '\n')
cin.get(next);
strcount(input);
cout << "Enter next line (empty line to quit):" << endl;
cin.get(input, ArSize);
}
cout << "Bye!" << endl;
return 0;
}
void strcount(const char * str) {
// 局部变量加static,无论调用多少次这个函数,该变量只会在第一次初始化
static int total = 0;
int count = 0;
while (*str) {
count++;
str++;
}
total += count;
cout << count << " characters." << endl;
cout << total << " characters total." << endl;
}
定位new运算符的使用
#include <iostream>
#include <new>
using namespace std;
const int BUF = 512;
const int N = 5;
char buffer[BUF];
int main(){
double *pd1, *pd2;
int i;
cout << "Calling new and placement new: " << endl;
// 用常规new运算符为N个double类型开辟内存空间
pd1 = new double[N];
// 用定位new运算符为N个double类型开辟内存空间
pd2 = new (buffer) double[N];
// 赋值
for (int i = 0; i < N; i++) {
pd2[i] = pd1[i] = 1000 + 20.0 * i;
}
cout << "pd1 = " << pd1 << ", buffer = " << (void *)buffer << endl;
// 打印pd1和pd2的地址
for (int 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: " << endl;
double *pd3, *pd4;
pd3 = new double[N];
pd4 = new(buffer) double[N]; // 会覆盖掉原来地址里的值
for (int i = 0; i < N; i++) {
pd4[i] = pd3[i] = 1000 + 40.0 * i;
}
for (int 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: " << endl;
delete[] pd1;
pd1 = new double[N]; // 删了重新new(申请和之前相同的地方)
pd2 = new(buffer + N * sizeof(double)) double[N]; // 地址往后偏移5个double类型的长度
for (int i = 0; i < N; i++) {
pd2[i] = pd1[i] = 1000 + 60.0 * i;
}
for (int i = 0; i < N; i++) {
cout << pd1[i] << " at " << &pd1[i] << ";";
cout << pd2[i] << " at " << &pd2[i] << endl;
}
delete[] pd1;
delete[] pd3; // pd2和pd4是定位new开辟出来的,delete不能用于定位new
return 0;
}
9.3 名称空间
当名称空间和声明区域定义了相同名称(伪代码)
namespace Jill{
double bucket(double n) {...}
double fetch;
struct Hill {...};
}
char fetch; // 全局变量
int main(){
using namespace Jill; // 使用using编译指令
Hill Thrill; // 创建一个Jill::Hill 的结构
double water = bucket(2); // 使用Jill::bucket()
double fetch; // 不会出错,Jill::fetch被隐藏
cin >> fetch; // 读入一个数据到局部变量fetch
cin >> ::fetch; // 读入一个数据到全局变量fetch
cin >> Jill::fetch; // 读入一个变量到Jill::fetch
...
}
int foom(){
Hill top; // 会出错
Jill::Hill crest; // 可用
}
名称空间示例(打印人名及欠款)
头文件namesp.h
#pragma once
#include <string>
namespace pers {
struct Person {
std::string fname;
std::string lname;
};
void getPerson(Person &rp);
void showPerson(const Person &rp);
}
namespace debts {
using namespace pers;
struct Debt {
Person name;
double amount;
};
void getDebt(Debt &rd);
void showDebt(const Debt &rd);
double sunDebts(const Debt ar[], int n);
}
源代码namessp.cpp
#include <iostream>
#include "namesp.h"
int main() {
using debts::Debt;
using debts::showDebt;
Debt golf = { {"Micheal", "Jordan"}, 120.0 };
showDebt(golf);
return 0;
}
源代码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 sunDebts(const Debt ar[], int n) {
double total = 0;
for (int i = 0; i < n; i++) {
total += ar[i].amount;
}
return total;
}
}