文章目录
- getline的用法
- empty的用法
- 计算字符串长度的两种方式
- stringstream 用法
- 指针
- 指针的用处
- C++ read()和write()读写二进制文件
- 首先为什么要使用read()和write()函数
- C++ ostream::write()方法写文件
- C++ istream::read()方法读文件
- sscanf_s按格式读取使用方法及时注意事项
- 使用stringstream按指定格式写文件
- 速度之巅,位图算法
- 多重继承类的菱形继承需要注意
- 使用虚继承后
- cin.ignore用法
- 调用> < == 和[ ] 普通类型 => 类类型 类类型 => 转普通类型 类类型 => 类类型 做重载运算符
- 子类和父类的构造函数的调用顺序
getline的用法
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
int main (void){
string x;
cout<<"请输入字符串:";
getline(cin,x);//getline==读取一行,遇到换行符结束
cout<<x;
system("pause");
return 0;
}
ps:getline()将会抛弃换行符\n,getline会自动把换行符\n换成字符串结束符\0,get()将会保留换行符\n,使用get()的时候最好在加一句get(),把输入缓冲区的\n读掉;
empty的用法
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
int main (void){
string x;
cout<<"请输入字符串:";
getline(cin,x);//getline==读取一行,遇到换行符结束
cout<<x<<endl;
if(x.empty()==true){//empty可以判断是否空字符串,如果是空字符串,结果为true,为真,否则结果是false,假
cout<<"你输入的是空字符串"<<endl;
}
system("pause");
return 0;
}
计算字符串长度的两种方式
//size
//length
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
int main (void){
string x;
cout<<"请输入字符串:";
getline(cin,x);//getline==读取一行,遇到换行符结束
cout<<x<<endl;
if(x.empty()==true){//empty可以判断是否空字符串,如果是空字符串,结果为true,为真,否则结果是false,假
cout<<"你输入的是空字符串"<<endl;
}
//两种计算字符串长度的方式
//size
//length
cout<<"字符串长度为:"<<x.size()<<endl;
cout<<"字符串长度为:"<<x.length()<<endl;
system("pause");
return 0;
}
stringstream 用法
stringstream 可以将所有输入数据转换成字符串
需要包含头文件#include
#include <iostream>
#include <windows.h>
#include <sstream>
using namespace std;
int main(void) {
stringstream ret;
ret <<"你好"<<" " << "吃了嘛";
//ret.str();
cout << ret.str() << endl;
return 0;
}
ps:注意一定要用str()进行字符串转换
指针
#include <iostream>
#include <Windows.h>
using namespace std;
int main(void) {
int i = 1024;
int* p = &i;
cout << &p << " " << &i << " " << p << " " << *p << endl;
system("pause");
return 0;
}
指针自身的地址是&p, 变量i的地址是&i,p是指针指向变量的地址,也就是i的地址,p是指针指向变量里面的值。
指针的用处
1.函数的值传递,无法通过调用函数,来修改函数的实参.
2.被调用函数需要提供更多的“返回值”给调用函数
3.减少值传递时带来的额外开销,提高代码执行效率
C++ read()和write()读写二进制文件
首先为什么要使用read()和write()函数
已文本方式存储数据,一是浪费空间,二是后期难以查找因为每一个数据占的字节数不一样.以二进制存储文件每个数据所用字节都是一样的,方便查找定位
值得一提的是,要实现以二进制形式读写文件,<< 和 >> 将不再适用,需要使用 C++ 标准库专门提供的 read() 和 write() 成员方法。其中,read() 方法用于以二进制形式从文件中读取数据;write() 方法用于以二进制形式将数据写入文件。
C++ ostream::write()方法写文件
ofstream 和 fstream 的 write() 成员方法实际上继承自 ostream 类,其功能是将内存中 buffer 指向的 count 个字节的内容写入文件,基本格式如下:
ostream & write(char* buff, int count);
其中,buff 用于指定要写入文件的二进制数据的起始位置;count 用于指定写入字节的个数。
也就是说,该方法可以被 ostream 类的 cout 对象调用,常用于向屏幕上输出字符串。同时,它还可以被 ofstream 或者 fstream 对象调用,用于将指定个数的二进制数据写入文件。
同时,该方法会返回一个作用于该函数的引用形式的对象。举个例子,obj.write() 方法的返回值就是对 obj 对象的引用。
需要注意的一点是,write() 成员方法向文件中写入若干字节,可是调用 write() 函数时并没有指定这些字节写入文件中的具体位置。事实上,write() 方法会从文件写指针指向的位置将二进制数据写入。所谓文件写指针,是是 ofstream 或 fstream 对象内部维护的一个变量,文件刚打开时,文件写指针指向的是文件的开头(如果以 ios::app 方式打开,则指向文件末尾),用 write() 方法写入 n 个字节,写指针指向的位置就向后移动 n 个字节。
演示
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name;
int age;
ofstream outfile;
outfile.open("user.dat", ios::out | ios::trunc | ios::binary);
while (1) {
cout << "请输入姓名: [ctrl+z退出] ";
cin >> name;
if (cin.eof()) { //判断文件是否结束
break;
}
outfile << name << "\t";
cout << "请输入年龄: ";
cin >> age;
//outfile << age << endl; //会自动转成文本方式写入
outfile.write((char*)&age, sizeof(age));//使用write()
}
// 关闭打开的文件
outfile.close();
system("pause");
return 0;
}
写入文件后会生成一个user.dat的二进制文件,使用文本打开会是乱码,可以使用Nopetad++打开,使用16进制查看
C++ istream::read()方法读文件
ifstream 和 fstream 的 read() 方法实际上继承自 istream 类,其功能正好和 write() 方法相反,即从文件中读取 count 个字节的数据。该方法的语法格式如下:
istream & read(char* buff, int count);
其中,buff 用于指定读取字节的起始位置,count 指定读取字节的个数。同样,该方法也会返回一个调用该方法的对象的引用。
和 write() 方法类似,read() 方法从文件读指针指向的位置开始读取若干字节。所谓文件读指针,可以理解为是 ifstream 或 fstream 对象内部维护的一个变量。文件刚打开时,文件读指针指向文件的开头(如果以 ios::app 方式打开,则指向文件末尾),用 read() 方法读取 n 个字节,读指针指向的位置就向后移动 n 个字节。因此,打开一个文件后连续调用 read() 方法,就能将整个文件的内容读取出来。
演示
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name;
int age;
ifstream infile;
infile.open("user.dat", ios::in | ios::binary);
while (1) {
infile >> name;
if (infile.eof()) { //判断文件是否结束
break;
}
cout << name << "\t";
// 跳过中间的制表符
char tmp;
infile.read(&tmp, sizeof(tmp));
//infile >> age; //从文本文件中读取整数, 使用这个方式
infile.read((char*)&age, sizeof(age));
cout << age << endl; //文本文件写入
}
// 关闭打开的文件
infile.close();
system("pause");
return 0;
}
在使用 read() 方法的同时,如果想知道一共成功读取了多少个字节(读到文件尾时,未必能读取 count 个字节),可以在 read() 方法执行后立即调用文件流对象的 gcount() 成员方法,其返回值就是最近一次 read() 方法成功读取的字节数
sscanf_s按格式读取使用方法及时注意事项
话不多说,上代码
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <Windows.h>
using namespace std;
int main(void)
{
char name[32];
int age;
string line;
ifstream infile;
infile.open("user.txt");
while (1) {
getline(infile, line);
if (infile.eof()) { //判断文件是否结束
break;
}
sscanf_s(line.c_str(), "姓名:%s 年龄:%d", name, sizeof(name),&age);
cout << "姓名:" << name << "\t\t年龄:" << age << endl;
}
infile.close();
system("pause");
return 0;
}
sscanf_s(line.c_str(), "姓名:%s 年龄:%d", name, sizeof(name),&age);
sscanf_s中的line.c_str(),c_str()是把字符串转换成const char*类型
需要注意的是,这里面的格式一定要对上"姓名:%s 年龄:%d",必须和文本格式一样,中间空一个空格可以跳过多个空格,文件的的:符号是中文方式的:符号,这里也必须也是中文的:符号,英文:符号及这里也是英文的:符号
使用stringstream按指定格式写文件
话不多说,上代码
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string name;
int age;
ofstream outfile;
outfile.open("user.txt", ios::out | ios::trunc);
while (1) {
cout << "请输入姓名: [ctrl+z退出] ";
cin >> name;
if (cin.eof()) { //判断文件是否结束
break;
}
cout << "请输入年龄: ";
cin >> age;
stringstream s;
s << "name:" << name << "\t\tage:" << age << endl;
outfile << s.str();
}
// 关闭打开的文件
outfile.close();
system("pause");
return 0;
}
这里就是使用stringstream进行格式化输入
使用stringstream需要加上头文件#include
速度之巅,位图算法
说白了就是空间换时间
问题
有很多不重复的整数, 其中最大值不超过40亿, 最小值是0.
要求判断某个指定的整数, 是否在这个集合中.
最快的算法:
使用位图算法。
使用2个字节,表示16个数(0-15)的状态(有或者没有)
如果数据为【5,1,7,15,0,4,6,10】,则存储状态为:
#include <stdio.h>
#include <Windows.h>
void init(char *data, int len) {
// 根据实际需求来实现.
// 这里只是为了测试后面的算法效果, 假设:
// 能够被3整数的数, 都在这个集合中.[假设的需求]
unsigned int n = len * 8; //一共有n个数据
for (unsigned int i = 0; i < n; i++) {
// 假设: 能够被3整数的数, 都在这个集合中.[假设的需求]
if (i % 3 == 0) {
//计算这个位对应哪个字节
char *p = data + i / 8;
*p = *p | (1 << (i % 8));
}
}
}
// 位图算法
bool check(char *data, int len, int value) {
// 定位到指定的字节
char *p = data + value / 8;
// 判断这个字节中指定的位是否为1
bool ret = *p & (1 << (value % 8));
return ret;
}
int main(void) {
// 很配一块足够的内存, 用来表示位图
unsigned int n = 4000000000;
int len = n / 8 + 1;
char *data = (char*)malloc(len);
memset(data, 0, len); //清零
// 装载数据集合(只需要装载一次)
init(data, len);
while (1) {
printf("请输入要检测的数: [输入-1退出] ");
int value;
scanf_s("%d", &value);
if (value == -1) {
break;
}
if (check(data, len, value)) {
printf("%d在数据集合中\n", value);
}
else {
printf("%d不在数据集合中\n", value);
}
}
system("pause");
return 0;
}
多重继承类的菱形继承需要注意
菱形继承子类访问父类的成员的时候,不能确定是访问那一个父类,而且也是两块内存,需要使用虚继承和虚基类,可以让两个父类两块内存,变成一块内存
代码示范
改进前
#include <iostream>
#include <string>
#include <Windows.h>
using namespace std;
// 电话类
class Tel {
public:
Tel() {
this->number = "未知";
}
protected:
string number; //电话号码;
};
// 座机类
class FixedLine : public Tel {
};
// 手机类
class MobilePhone :public Tel {
};
// 无线座机
class WirelessTel :public FixedLine, public MobilePhone {
public:
void setNumber(const char *number) {
//this->number = number; //错误, 指定不明确
this->FixedLine::number = number; //this可以省略
}
string getNumber() {
//return MobilePhone::number;
return MobilePhone::number;
}
};
int main(void) {
WirelessTel phone;
phone.setNumber("13243879166");
cout << phone.getNumber() << endl; //打印未知
system("pause");
return 0;
}
使用虚继承后
关键字:virtual
#include <iostream>
#include <string>
#include <Windows.h>
using namespace std;
// 电话类
class Tel { //虚基类
public:
Tel() {
this->number = "未知";
}
protected:
string number; //电话号码;
};
// 座机类
class FixedLine : virtual public Tel { //虚继承
};
// 手机类
class MobilePhone : virtual public Tel { //虚继承
};
// 无线座机
class WirelessTel :public FixedLine, public MobilePhone {
public:
void setNumber(const char *number) {
this->number = number; //直接访问number
}
string getNumber() {
return this->number; //直接访问number
}
};
int main(void) {
WirelessTel phone;
phone.setNumber("13243879166");
cout << phone.getNumber() << endl;
system("pause");
return 0;
}
cin.ignore用法
cin.ignore(count, c);
从输入流中提取并丢弃字符,直到遇到下列三种情况
1.提取的字符达到了参数count指定的数量
2.在输入序列中遇到文件结束(EOF)
3.输入序列中的下一个字符为参数c指定的字符(这个字符会被提取并丢弃)
count常常取:
std::numeric_limitsstd::streamsize::max() 相当于IO流的最大字符个数
常见用法:(把标准输入缓冲区cin的所有数据都清空)
cin.ignore(std::numeric_limits::max(), ‘\n’);
有些编译器会出现错误
可以改为:
cin.ignore((std::numeric_limits::max)(), ‘\n’);
项目代码
#include <iostream>
#include <Windows.h>
#include <fstream>
using namespace std;
//输入任意多个整数, 把这些数据保存到文件data.txt中.
//如果在输入的过程中, 输入错误, 则提示用户重新输入.
//指导用户输入结束(按ctrl + z)
//[每行最多保存10个整数]
int main(void) {
ofstream file;
file.open("data.txt", ios::trunc);
if (!file.is_open()) {
cout << "文件打开失败!";
file.close();
return 1;
}
cout << "按[ctrl+z]结束输入" << endl;
//cout << "输入0结束输入" << endl;
int n = 0;
while (true) {
int integer = NULL;
cout << "请输入任意多个整数:";
cin >> integer;
if (cin.eof()) {
break;
}
while (cin.fail()) {
cin.clear(); //清除错误标志
//cin.sync();
//cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
cin.ignore((std::numeric_limits<streamsize>::max)(), '\n');
cout << "输入错误,请重新输入:";
cin >> integer;
}
file << integer << "\t";
if (++n % 10 == 0) {
file << endl;
}
}
file.close();
system("pause");
return 0;
}
调用> < == 和[ ] 普通类型 => 类类型 类类型 => 转普通类型 类类型 => 类类型 做重载运算符
代码
boy.h
#pragma once
#include <string>
#include <iostream>
#include <ostream>
#include <istream>
#define GET_AGE "age"
#define GET_SALARY "salary"
#define GET_POTENTIAL "potential"
typedef enum {
getage,
getsalary,
getpotential
}cf;
using namespace std;
class boy {
public:
boy(const char* name, int age, int salary, int potential);
~boy();
std::string description();
boy(const boy& boy); //拷贝构造函数
boy& operator=(const boy& boy1); //赋值构造函数
bool operator>(const boy& boy1);
bool operator<(const boy& boy1);
bool operator==(const boy& boy1);
int operator[](std::string intdex) const;
int operator[](int intdex) const;
//使用类的成员函数作为<<重载运算符(不推荐)
//ostream& operator<<(ostream& os) const;
//istream& operator>>(istream& is);
//
//使用友元函数作为<<重载运算符(推荐)
friend ostream& operator<<(ostream& os, const boy& boys);
friend istream& operator>>(istream& is, boy& boys);
//重载类型运算符 普通类型 => 类类型
boy(const int salary);
boy(const char* name);
//重载类型运算符 类类型 => 普通类型
operator int() const;
operator char* () const;
private:
char* name;
int age;
int salary;
int potential; //潜力
int synthesize() const;
unsigned int id;
static int ID;
};
boy.cpp
#include "boy.h"
#include <sstream>
#include <string>
using namespace std;
int boy::ID = 0;
boy::boy(const char* name, int age, int salary, int potential)
{
if (!name) {
name = "未命名";
}
this->name = new char[strlen(name) + 1];
strcpy_s(this->name, strlen(name) + 1, name);
this->age = age;
this->salary = salary;
this->potential = potential;
this->id = ++ID;
}
boy::boy(const int salary)
{
this->salary = salary;
const char* d1 = "未命名";
name = new char[strlen(d1) + 1];
strcpy_s(name, strlen(d1) + 1, d1);
this->age = 0;
this->potential = 0;
this->id = ++ID;
}
boy::boy(const char* name) {
this->name = new char[strlen(name) + 1];
strcpy_s(this->name, strlen(name) + 1, name);
this->age = 0;
this->salary = 0;
this->potential = 0;
this->id = ++ID;
}
boy::operator int() const{
return salary;
}
boy::operator char* () const{
return name;
}
boy::boy(const boy& boy)
{
if (name) {
delete name;
}
name = new char[strlen(boy.name) + 1];
strcpy_s(name, strlen(boy.name) + 1, boy.name);
age = boy.age;
salary = boy.salary;
potential = boy.potential;
}
boy::~boy()
{
if (name) {
delete name;
}
}
boy& boy::operator=(const boy& boy1) {
if (name) {
delete name;
}
name = new char[strlen(boy1.name) + 1];
strcpy_s(name, strlen(boy1.name) + 1, boy1.name);
this->age = boy1.age;
this->salary = boy1.salary;
this->potential = boy1.potential;
return *this;
}
bool boy::operator>(const boy& boy1)
{
if (synthesize() > boy1.synthesize()) {
return true;
}
else {
return false;
}
}
bool boy::operator<(const boy& boy1)
{
if (synthesize() < boy1.synthesize()) {
return true;
}
else {
return false;
}
}
bool boy::operator==(const boy& boy1) {
if (synthesize() == boy1.synthesize()) {
return true;
}
else {
false;
}
}
int boy::operator[](string intdex) const
{
if (intdex == "potential") {
return potential;
}
else if (intdex == "age") {
return age;
}
else if (intdex == "salary") {
return salary;
}
}
int boy::operator[](int intdex) const
{
if (intdex == 0) {
return age;
}
else if (intdex == 1) {
return salary;
}
else if (intdex == 2) {
return potential;
}
}
//istream& boy::operator>>(istream& is)
//{
// string name2;
// is >> name2 >> age >> salary;
// name = new char[(name2.length() + 1) / sizeof(char)];
// //name = (char*)malloc((name2.length() + 1) / sizeof(char));
// strcpy_s(name, (name2.length() + 1), name2.c_str());
//
// return is;
//}
//ostream& boy::operator<<(ostream& os) const
//{
// os << id << " 姓名:" << name << "\t" << "年纪:" << age << "\t" << "薪资:" << salary << "\t" << "潜力:" << potential;
// return os;
//}
//ostream& boy::operator<<(ostream& os) const
//{
// os << id << " 姓名:" << name << "\t" << "年纪:" << age << "\t" << "薪资:" << salary << "\t" << "潜力:" << potential;
// return os;
//}
string boy::description() {
stringstream ret;
ret << id << " 姓名:" << name << "\t" << "年纪:" << age << "\t" << "薪资:" << salary << "\t" << "潜力:" << potential;
return ret.str();
}
int boy::synthesize() const {
int tmp = salary + ((age - 100) * 100) + (potential * 100);
return tmp;
}
ostream& operator<<(ostream& os, const boy& boys) {
os << boys.id << " 姓名:" << boys.name << "\t" << "年纪:" << boys.age << "\t" << "薪资:" << boys.salary << "\t" << "潜力:" << boys.potential;
return os;
}
istream& operator>>(istream& is, boy& boys) {
string name2;
is >> name2 >> boys.age >> boys.salary;
boys.name = new char[(name2.length() + 1) / sizeof(char)];
strcpy_s(boys.name, name2.length() + 1, name2.c_str());
return is;
}
man.h
#pragma once
#include <ostream>
using namespace std;
class boy;
class man {
public:
man(const char* name, int age, int salary);
~man();
man(const boy& boys);
friend ostream& operator<<(ostream& os, man& mans);
private:
char* name;
int age;
int salary;
};
ostream& operator<<(ostream& os, man& mans);
man.cpp
#include "man.h"
#include "boy.h"
#include <iostream>
using namespace std;
man::man(const char* name, int gae, int salary) {
if (!name) {
name = "未命名";
}
name = new char[strlen(name) + 1];
strcpy_s(this->name,strlen(name)+1,name);
this->age = age;
this->salary = salary;
}
man::~man()
{
if(name){
delete name;
}
}
man::man(const boy& boys)
{
int len = strlen((char*)boys) + 1;
name = new char[len];
strcpy_s(name,len,(char*)boys);
this->age = boys[getage];
this->salary = boys[getsalary];
}
ostream& operator<<(ostream& os, man& mans)
{
os << "姓名:" << mans.name << "年龄:" << mans.age << "薪资:" << mans.salary;
return os;
}
main.cpp
#include <iostream>
#include <Windows.h>
#include <string>
#include "boy.h"
#include "man.h"
using namespace std;
int main(void) {
/*
调用=赋值构造函数
boy f1("胡景华",19,50000,80);
boy f2;
boy f3;
f3 = f2 = f1;
cout << f1.description() << endl;
cout << f2.description() << endl;
cout << f3.description() << endl;
*/
/* 调用>运算符重载
boy s1("胡景华", 19, 60000, 75);
boy s2("胡景华", 18, 50000, 80);
if (s1 > s2) {
cout << s1.description() << "更好" << endl;
}
else {
cout << s2.description() << "更好" << endl;
}
*/
/* 调用<运算符重载
boy s1("胡景华", 19, 60000, 75);
boy s2("胡景华", 18, 50000, 80);
if (s1 < s2) {
cout << s2.description() << "更好" << endl;
}
else {
cout << s1.description() << "更好" << endl;
}
*/
/* 调用==运算符重载
boy s1("胡景华", 19, 60000, 80);
boy s2("胡景华", 19, 60000, 80);
if (s1 == s2) {
cout << s1.description() << "和" << s2.description() << "一样好" << endl;
}
else if(s1>s2){
cout << s1.description() << "更好" << endl;
}
else if (s1 < s2) {
cout << s2.description() << "更好" << endl;
}
*/
/* 使用[]下标运算符重载
boy t1("胡景华", 19, 60000, 80);
//使用[]下标字符串进+宏定义行对比访问
cout << "年纪" << t1[GET_AGE] << "薪资:" << t1[GET_SALARY] << "潜力:" << t1[GET_POTENTIAL] << endl;
//使用[]下标+枚举进行对比访问
cout << "年纪" << t1[getage] << "薪资:" << t1[getsalary] << "潜力:" << t1[getpotential] << endl;
*/
/*
//使用<< >>重载运算符
boy s1("胡景华", 19, 60000, 75);
boy s2("胡景华", 18, 50000, 80);
//使用类成员函数作为<< >>重载运算符的调用方法
<<重载运算符的使用方法
s1<<cout;
s2<<cout;
>>重载运算符的使用方法
s1<<cin;
s2<<cin;
cout << s1 << endl;
cout << s2 << endl;
cin >> s1;
cin >> s2;
cout << s1 << endl;
cout << s2 << endl;
*/
// 重载类型运算符 普通类型 => 类类型
boy boys1 = 100000;
boy boys = "喜羊羊";
cout << boys1 << endl;
cout << boys << endl;
//重载类型运算符 类类型 => 普通类型
int salary = boys1;
char* name = boys;
cout << name << endl;
cout << salary << endl;
//重载类型运算符 类类型 => 类类型
boy boy1("胡景华",19,100000,90);
man man1 = boy1;
cout << boy1 << endl;
cout << man1 << endl;
system("pause");
return 0;
}
子类和父类的构造函数的调用顺序
当创建子类对象时, 构造函数的调用顺序:
静态数据成员的构造函数 -> 父类的构造函数 -> 非静态的数据成员的构造函数 -> 自己的构造函数
注意:
无论创建几个对象, 该类的静态成员只构建一次, 所以静态成员的构造函数只调用1次!!!
#include <iostream>
#include <Windows.h>
using namespace std;
class M {
public:
M() {
cout << __FUNCTION__ << endl;
}
};
class N {
public:
N() {
cout << __FUNCTION__ << endl;
}
};
class A {
public:
A() {
cout << __FUNCTION__ << endl;
}
};
class B : public A {
public:
B() {
cout << __FUNCTION__ << endl;
}
private:
M m1;
M m2;
static N ms;
};
N B::ms; //静态成员
int main(void) {
B b;
system("pause");
}
执行:
N::N 静态数据成员的构造函数
A::A 父类的构造函数
M::M 非静态数据成员的构造函数
M::M 非静态数据成员的构造函数
B::B 自己的构造函数
子类的析构函数的调用顺序,和子类的构造函数的调用顺序相反!!!
记住,相反即可。
#include <iostream>
#include <Windows.h>
using namespace std;
class M {
public:
M() {
cout << __FUNCTION__ << endl;
}
~M() {
cout << __FUNCTION__ << endl;
}
};
class N {
public:
N() {
cout << __FUNCTION__ << endl;
}
~N() {
cout << __FUNCTION__ << endl;
}
};
class A {
public:
A() {
cout << __FUNCTION__ << endl;
}
~A() {
cout << __FUNCTION__ << endl;
}
};
class B : public A {
public:
B() {
cout << __FUNCTION__ << endl;
}
~B() {
cout << __FUNCTION__ << endl;
}
private:
M m1;
M m2;
static N ms;
};
N B::ms; //静态成员
int main(void) {
{
B b;
cout << endl;
}
system("pause");
}
执行:
N::N
A::A
M::M
M::M
B::B
B::~B
M::~M
M::~M
A::~A