c++笔记

21 篇文章 0 订阅

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

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值