C++ Learning_1

C++小记

/*********************类的继承***********************/
代码的重用
派生类可以访问基类中所有非私有成员
不继承基类的构造函数,析构函数,拷贝构造函数
基类的重载运算符
基类的友元函数
protected 类内和子类可访问

//继承类型:public private protected
基类的私有成员不能直接被派生类访问
多继承
class Rectangle: public Shape,public PaintCost{//公有继承

}
class Person{
	public:
		string m_strName;
		int m_nAge;
		bool m_bIsMale;

```cpp
	string GetName(){
		return m_strName;
	}
	int GetAge(){
		return m_nAge;
	}
	bool IsMale(){
		return ...
	}
```
}
#ifndef TABTENN1_H_
#define TABTENN1_H_
#include <string>
using std::string;
class TableTennisPlayer{
	...
}
class RatedPlayer : public TableTennisPlayer{
	
};
#endif

//派生类和基类的关系
基类指针和引用可以指向派生类对象
可以将基类对象初始化为派生类对象:
RatedPlayer olaf1(1840,"");
TableTennisPlayer olaf2(olaf1);//调用隐式复制构造函数TableTennisPlayer(const TableTennisPlayer &);

TableTennisPlayer winner;
winner = olaf1;//调用隐式赋值函数:TableTennisPlayer & operator = (const TableTennisPlayer &)const;

//继承可以在基类上添加属性,但是不能够删除属性
//一个构造函数的代码
RatedPlayer::RatedPlayer(unsigned int r,const string & fn,const string &ln,bool ht)
:TableTennisPlayer(fn,ln,ht)//初始化成员列表,调用了基类的构造函数//参数从派生类构造函数传递给基类构造函数
{//
	rating = r;
}
如果不调用基类的构造函数,程序将使用基类的默认构造函数
//派生类对象过期时,系统首先调用了派生类对象的构造函数,再调用基类的析构函数

//多态的公有继承同一个方法在派生类和基类的行为是不同的
基类:
class Base{
	public:
		virtual void ViewAcct()const;//virtual
}
class BasePlus : public Base{
	public:
		virtual coid ViewAcct()const;
}
virtual关键词说明://在基类声明了虚方法后,派生类会自动生成虚方法
如果方法通过引用和指针而不是对象调用的,没有加virtual关键字的的系统根据引用类型和指针类型
来选择方法//加了Virtual 关键字指向的对象的类型来选择方法
Base dom();
BasePlus dot("");
Brass & b1_ref = dom;
Brass & b2_ref = dot;引用类型是Brass ,引用的是BrassPlus对象
b1_ref.ViewAcct();//use Brass::ViewAcct();
b2_ref.ViewAcct();//use Brass::ViewAcct();//use BrassPlus::ViewAcct()使用了Virtual
为基类声明一个虚析构函数是惯例

//如果用一个数组保存Brass和BrassPlus的对象是无法做到的,
//但是可以创建指向Brass的指针数组,Brass指针可以指向BRassPlus对象,使用一个数组来表示多种类型的对象就是多态性
Brass * p_clients[CLIENTS];

#include<iostream>
#include<string>
#include"brass.h"
const int CLIENTS = 4;
int main(){
	using std::cin;
	using std::count;
	using std::endl;

	Brass * p_clients[CLIENTS];
	std::string temp;
	long tempnum;
	double tempbal;
	char kind;
	
	for (int i =0;i<CLIENTS;i++){
		cout << "enter client's name";
		getline(cin,temp);
		cin >> tempnum;
		cin >> tempbal;
		while(cin>>kind && (kind !='1'&& kind !='2'))
			cout << "enter either 1 or 2";
		if(kind == '1')
			p_clients[i] = new Brass(temp,tempnum,tempbal);
		else{
			double tmax,trate;
			cin >> tmax;
			cint >> trate;
			p_clients[i] = neew BrassPlus(temp,tempnum,tempbal,tmax,trate);
		}
		while(cin.get() != '\n')
			continue;
	}
	cout << endl;
	for (int i = 0;i<CLIENTS;i++){
		p_clients[i]->ViewAcct();
		cout << endl;
	}
	for (int i = 0;i<CLENTS;i++){
		delete p_clients[i];//free memory
	}
}
//为何需要虚析构函数?
如果析构函数不是虚的,则将调用对应指针类型的析构函数,这意味着只有brass的析构函数被调用,即使指针指向的是brassplus对象
将调用相应对象类型的析构函数;

//静态联编和动态联编
c++不允许一种类型的地址赋给另一种类型的指针
不允许一种类型的引用指向另一种类型;
但是基类的引用或指针可以指向派生类的对象
Brass * pb = &dilly;
将派生类的引用或指针转换为基类的引用或指针被称为向上强制类型转换//没有问题,包含关系
将基类指针或引用转换为派生类的指针或引用为向下强制类型转换,如果不使用显示类型转换,是不被允许的
隐式向上强制转换使基类指针或引用可以指向基类对象或派生类对象,因此需要动态联编,用virtual来实现

BrassPlus ophelia;
Brass * bp;
bp = &ophelia;
bp->ViewAcct();//没有调用虚方法就调用的使Brass的函数;
//为何不摒弃静态联编?
静态联编的效率更高,如果派生类不重新定义基类的任何方法,就用静态联编,效率更高
//虚函数的实现原理:
给每个对象添加一个隐藏成员,保存了一个指向函数地址的数组指针
对于每个类,编译器都要创建一个虚函数地址表
对于每个函数的调用,都要在表中查找地址

Employee * pe = new Singer;
delete pe;//~Employee() or ~Singer();
如果是静态联编则调用~Employee(),释放Singer对象中的Employee部分指向的内存,但不会释放新的类成员指向的内存
如果是动态联编,会先用~Singer()释放Signer组件指向的内存,然后调用~Employee释放它的内存

友元不能是虚函数,因为友元不是类成员,只有成员才能是虚函数

public:
	virtual void showperks(int a)const;//base
public:
	virtual void showperks()const;//重新定义不会生成两个函数的重载版本,而是隐藏所有的同名基类版本
	返回类型协变:返回基类的引用变成返回派生类的引用或指针
	如果积累的声明被重载,则应在派生类中重新定义所有的基类版本;

//访问控制protected
对于派生类来说protected和公有成员相似
对于外部世界,行为与私有成员相似

/*抽象基类*/
circle和ellipse有很多共同点
可以从这两个类中抽象出共同的特性,将这些特性放在一个ABC中,然后从abc派生出circle和ellipse类

c++通过纯虚函数提供未实现的函数
public:
	BaseEllipse(double x0 = 0,double y0 = 0) : x(x0),y(y0){};
	virtual BaseEllipse(){};
	virtual double Area() const = 0;//纯虚函数,原型中=0的虚函数为纯虚函数
	void Move(int nx,ny) = 0;//基类成为抽象的
	void BaseEllipse::Move(int nx,ny){x=nx;y=ny;}//仍可以在实现文件中定义

class Circle:public BaseEllipse{};//具体类,可以用BaseEillpse的指针数组同时管理这两种对象

//actabc.h
class AcctABC{

}
AcctBBC::AcctABC(const string & s,long an,double bal){
	fullName = s;
	accaNum = an;
}
BrassPlus::BrassPlus(const string & s,long an,double bal,double m1,double r):AcctABC(s,an,bal){
	maxLoan = ml;
	owesBank = 0.0;
	rate = r;
}
void BrassPlus::ViewAcct()const{
	Formatting f = SetFormat();

	if (amt<=bal)
		AcctABC::Withdraw(amt);
	else{
		...
	}
}
/*继承和动态内存分配*/



/******************类和动态内存分配***************************/
strngbad.h//
#include <iostream>
#ifndef STRNGBAD_H_
#define STRNGBAD_H_

class StringBad{
	private:
		char * str;
		int len;
		static int num_strings;
	public:
		StringBad(const char*s);
		StringBad();
		~StringBad();

		friend std::ostream & operator<<(std::ostream & os,const StringBad & st);
};
#endif


#include<cstring>
#include"stringbad.h"

int StringBad (const char* s){
	len = std::strlen(s);
	str = new char[len + 1];
	std::strcpy(str,s);
	num_strings++;
	cout << num_strings << ": \" "<< str<< "\" default object created\n";
}
StringBad::StringBad(){
	len = 4;
	str = new char[4];
	std::strcpy(str,"C++");
	num_strins++;
	cout<< num_strings << ": \“ "<< str<< "\" default object creat\n";
}
StringBad::~StringBad(){
	--num_strings;
	delete [] str;
}

//int StringBad::num_strings = 0;//不能在类声明中初始化静态成员变量,声明中描述了如何分配内存,但不分配内存
point: 静态数据成员在类声明中声明,在类方法文件中初始化,使用作用域运算符来指出静态成员所属的类
静态成员是const整数类型或emun枚举型,则可以在类声明中初始化


//复制构造函数
StringBad ditto(motto);
StringBad metoo = motto;
StringBad also = StringBad(motto);
StringBad * pSt = new StringBad(motto);
显示复制构造函数
复制构造函数应当复制副本,而不是引用另一个对象的字符串

StringBad::StringBad(const StringBad & st){
	num_strings_++;
	len = st.len;
	str = new char[len+1];
	std::strcpy(str,st.str);
}

StringBad metoo = knot;//初始化用复制构造函数;
编写赋值运算符:
StringBad & StringBad::operator=(const StringBad & st){

	if(this == &st)
		return st;
	delete [] str;
	len=st.len;
	str= new char [ len+1];
}

//静态类成员函数
static int Howmany(){
	
}

调用方法:
int count = String::Howmany();//静态函数不与特定的对象相关联,因此静态函数只能使用静态成员

class String {

}

/***************使用类*************/
比起按值传递对象,传递引用速度快,使用的内存少
Time Time::Sum(const Time & t) const{
	Time sum;
	return sum;
}
如果返回类型为Time&,则为指向sum的引用,但是sum为局部对象,函数结束及删除,则指向一个不存在的对象
返回类型为Time,意味着程序在删除sum之前构造它的拷贝,调用函数将得到他的拷贝

/*运算符重载*/
public:
	Time operator+(const Time & t)const;

Time Time::operator+(const Time & t)const{
	Time sum;
	sum.minutes = minutes + t.minutes;
	return sum;
}

total = coding.operator+(fixing);
total = coding + fixing;//same

main 函数中:
int a , b , c;
Time A,B,C;
c=a+b;//int addition
C=A+B;//addition as defined for Time objects

/*友元*/
另一种形式的访问权限;
通过让函数成为类的友元,可以赋予该函数于类的成员函数相同的访问权限

Time Time::operator*(double mult)const{
	Time result;
	long totalminutes = ...;
}
A = B * 2.75;//左侧操作数是调用对象
A = B.operator*(2.75);

Time operator*(double m ,const Time & t);//非成员函数不可以直接访问类的私有数据
说明:虽然在类声明中声明,但不是成员函数,不能使用成员运算符来调用
不是成员函数但是和成员函数的访问权限相同,非成员函数不需要Time::限定符
Time operator*(double m,const Time &t){
}
类的友元函数是非成员函数但是访问权限和成员函数相同
类方法和友元只是表达类接口的两种不同机制

//重载<<运算符//访问什么对象的私有成员才必须是该类的友元函数
void operator<<(ostream & os,const Time & t)
{
	os << t.hours<<"hours"<<t.minutes<<"mintes";
}
cout << trip;

Time operator+(const Time & t)const{

}
friend Time operator+(const Time & t1,const Time & t2);

ostream & operator<<(ostream & os,const c_name & obj){
	os <<
	return os;
}
/*创建友元*/
第一步:在类声明中
friend Time operator*(double m , const Time &t);

友元函数不在类的作用域内,所以要使用
if(v.mode == vector::RECT//不能使用RECT)

Vector Vector::operator*(double n)const{
	return Vector(n*x, n*y);
}
friend function//
Vector operator*(double n,const Vector & a){
	return a*n;
}

Vector Vector::operator-(const Vector & b)const{
	return Vector(x - b.x,y-b.y);
}
diff = v1 - v2;
diff = v1.operator-(v2);

重载已重载的运算符
Vector Vector::operator-() const{
	retutn Vector(-x,-y);
}//特征标不同,可以重载运算符

using VECTOR::Vector;
//因为所有的Vector类方法的作用域为整个类,所以导入类名后,可以直接使用Vector的方法

/*类的自动转换和强制类型转换*/
数值类型转换可行:
int side = 3.33;
不自动转换不兼容类型:指针和整数时不同的类型
int * p = 10;error
此时用强制类型转换
int * p = (int *)10;

/*类的强制类型转换*/
//stonewt.h
#ifndef STONEWT_H_
#define STOMEWT_H_

class Stonewt{
	private:
		enum{Lbs_per_stn = 14};//static const int Lbs_pr_stn = 14
		int stone;
		double pds_left;
		double pounds;
	public:
		Stonewt(double lbs);
		Stonewt(int stn, double lbs);
		Stonewt();
		~Stonewt();
		void show_lbs()const;
		void show_stn()const;
};
#endif

#include <iostream>
using std::cout;
#include"stonewt.h"

Stonewt::Stonewt(double lbs)
{
	stone = int(lbs) / Lbs_per_stn;
	pds_left = int (lbs) % Lbs_per_stn + lbs - int(lbs);
	pounds = lbs;
}
Stonewt::Stonewt(int stn ,double lbs){
	stone = stn;
	pds_left = lbs;
}

Stonewt(double lbs);//将double类型转换为Stonewt类型
Stonewt myCat;
myCat = 19.36;//correct;
程序使用构造函数Stonewt(double)接受double参数19.36,转换为一个Stonewt对象,
创建临时的Stonewt对象,并将19.6作为初始化的值,采用
逐成员复制方式将该临时对象的内容复制到myCat中
一个参数的构造函数才可以作为转换函数
Stonewt(int a,double b);//两个参数不可转
Stonewt(int a ,double b  = 0);//可以转,隐式转换

显示转换:
mCat = Stonewt(1);

关闭自动转换的特性:加关键字explicit
explicit Stonewt(double lbs);

构造函数只能用于某种类型到某种类类型的转换,不可用于相反的转换
要进行相反的转换必须使用C++运算符函数——转换函数
double thinker = (double)wolfe;
//double thinker = double(wolfe);
创建转换函数 operator typename();//要转换为typeName的类型;
//point: 转换函数必须是类方法;不能指定返回类型;不能有参数
public:
	operator int()const;
	operator double()const;
...
stonewt1.cpp:
//conversion functions
Stonewt::operator int()const{
	return int (pounds + 0.5);
}
Stonewt::operator double()const{
	...
}
Stonewt poppins(9,2.8);
double p_wt = poppins;//隐式使用了转换为double类型的构造函数
int(poppins);//显示类型转换

cout<<poppins;//不可直接使用,存在二义性
存在多个转换时,可以使用
long gone = double(poppins);
//最好使用显示转换,避免隐式转换
public:
	explicit operator int() const;
	explicit operator double()const;

此时 int plb = poppins是错误的
Stone Stonewt::operator+(const Stonewt & st)const{
	double pds = pounds + st.pounds;
	Stonewt sum(pds);
	return sum;
}//成员函数重载加法函数

Stonewt operator+(const Stonewt & st1,const Stonewt & st2){
	return sum;
}//友元函数重载加法函数

total = penn + jdl;
total = operator+(dkkd,djs);

friend Stonewt operator+(double x , Stonewt & s);
total = pennyD + jennySt;//double + Stonewt
/********对象和类*****************/
///stock00.h
#ifndef STOCK00_H_
#define STOCK00_H_
45"sdfsf"
char a 's'
#include <string>
class Stock//类名大写
{
	private://default可省略
		std::string company;
		long shares;
		double a;
		void set_lot(){//内敛方法,可以inline限定符定义在类外
			share = ...
		}
	public://公共接口

};//勿漏
inline void Stock::set_lot(){

}
//stock00.cpp
定义成员函数时,需要作用于解析运算符(::)来标识函数所属的类
类方法可以访问类的private组件

#include <iostream>
#include"stock00.h"
void Stock::acquire(const std::string & co,long n,double pr)
{
	company = co;
	if...
}
void Stock::buy(long num,double price);

void Stock::show(){
	using std::cout;
	using std::ios_base;
	ios_base::fmtflags orig = cout.setf(ios_base::fixed,ios_base::floatfield);
	std::streamsize prec = cout.precision(3);
	...
	cout.setf(orig,ios_base::floatfield);
	cout.precision(prec);
}
/********类的构造函数和析构函数*****************/
Stock gift;
gitf.buy(...);//不能直接访问数据成员,只能通过成员函数访问

声明和定义构造函数
Stock::Stock(const string &co, long n,double pr)
{
	company = co;
}//private: string company_/m_company

Stock garment("ddd",d,5)//隐式使用等同于
Stock garment = Srock(...);

Stock *pstock = new Stock(..);//创建一个stock对象,初始化提供参数的值,并将该对象的地址
								//赋给pstock指针,可以用指针来管理对象

没有定义构造函数时系统才会用默认构造函数
有定义的构造函数时
Stock ddd;//错误,不能用默认的构造函数了
可以通过函数重载来定义不同的构造函数
Stock::Stock{
	company = "no name"
}

构造函数创建对象后,程序跟踪对象直到过期,过期则自动调用析构函数,完成清理工作
每个类只有一个析构函数
Stock类的析构函数 : ~Stock();//没有参数
Stock::~Stock(){
	cout<<"Bye"<<endl;
}//通常不在代码中显示使用,对象的类型不同则析构函数调用的时机不同
stock1 = Stock(..)//构造函数不仅仅用来初始化,stock1已经存在,该语句通过构造
					//函数创造一个新的临时的变量,然后将内容复制给stock1,随后程序调用析构函数删除该临时对象

列表初始化:
Stock hot = {...};
Stock hot{...};

const Stock land = Stock(...);
land.buy()//错误,因为show的代码无法保证所调用的对象不被修改

const 成员函数:
void show()const;
void Stock::show()const;//保证函数不会修改调用对象
只要类方法不修改调用对象,就将其声明为const


/**this指针**/
要使方法返回一个引用,该引用指向股票价值更高的对象
const Stock & topval(const Stock &)const;
括号中的const表明不会修改显示引用的对象,括号后的const表示不会修改被隐示访问的对象
top = stock1.topval(stock2);//显示访问stock2,隐示访问stock1

const Stock & Stock::topval(const Stock &)const{
	if(s.total > total)
		return s;
	else
		return *this;
}
//this是对象的地址,*this为对象,返回类型为引用意味着返回的是对象本身而不是副本

/*对象数组*/
Stock mustuff[4];
程序创建未被显示初始化的类对象时,总是调用默认的构造函数
const int STKS = 4;
Stock stock [STKS] = {
	Stock("NanoSmart",1.5);
	..
	Stock(..);
};

类作用域意味着不能从外部直接访问类成员,
Ik * pik = new Ik;
类只描述了对象的形式,并没有创建对象,因此,在创建对象前是没有用于存储值的空间

在类中定义常量的方式——关键字static
class Bakery
{
	private:
		static const int Months = 12;
		doube costs[Months];
};//这创建一个Months的常量,不存储在对象中,只有一个Months常量被所有Bakery共享//只能整型和枚举

typedef unsigned long Item;
Stack::Stack(){
	top = 0;
}

bool Stack::isempty() const{
	return top==0;
}

bool Stack::isfull() const{
	return top == MAX;
}
/////////////////////////////////////////////////////////////////
5种变量存储方式
自动
寄存器
静态(无链接性)代码块中使用static,作用域代码块
静态(外部链接性)不在任何函数内,作用域文件
静态(内部链接性)不在任何函数内使用static
静态变量的零初始化

int x;//zero-initialization
链接性为外部的变量叫外部变量或全局变量
多个文件中使用外部变量只需要在一个文件中定义声明,给变量分配存储空间:double up;
引用声明不给变量分配存储空间,引用已有的变量:extern int blem;
*程序越能避免对数据进行不必要的访问越能保持数据的完整性
外部变量不可以在两个文件中都定义声明
static int errors = 5//static 指出标识符errors 的链接性为内部,可以在其他文件中再定义
//file2
int errors //correct

/*无链接性的局部变量*/
将static的限定符用于在代码块中定义的变量
在代码块不活动时仍然存在
程序在启动时只进行一次初始化,及再次调用函数时不会重新初始化

/*thread_local*/
存储说明符号之一,register、static、extern(引用声明)
thread_local用于线程
/*cv-限定符*/
const
volatile?


mutable//即使结构或类的变量为const,其某个成员也可以被修改
struct  data{
	char name[30];
	mutable int accesses;
}
const全局变量的链接性是内部的
const int fingers = 10;//== static
这意味着每个文件都有自己的一组常量,而非共享常量,所以可以多个文件声明

若希望某个常量的链接性是外部的
extern const int figers = 10;//extern可以覆盖掉默认的内部链接性//此时只有一个文件对它初始化

/*函数的链接性*/
通常函数的链接性是静态外部的,所有文件可用
使用static则将链接性置为内部,一个文件中使用
static int private(double & x);
??内联函数,非内联函数
extern

/*动态分配内存*/
float *p_fees = new float [20];
new 分配的80b内存保存在内存中,直到delete运算符将其释放
分配内存并初始化
int * po = new int (6)

struct where {double x;double y;double z};
where * there = new where{2.5,563.3,23.5};

定位new运算符
#include<new>
double *pd2;
char buffer[BUF];
pd2 = new (buffer) double[N];
delete [] pd2;//incorrect

声明区域//文件或代码块
潜在作用域//声明点开始到声明区域结尾

/*关键字namespace*/
namespace Jack{
	double pail;
	void fetch();  //fuction prototype
	int pal;		//variable declaration
	struct Well{};	//structure declaration
}
名称空间可以是全局的,但不能位于代码块中,链接性为外部,除非它引用常量
任何名称空间中的名称都不会和其他名称空间发生冲突
可以不断添加
namespace Jack{
	int j;
}
访问方法:
Jack::pail = 12.36;

局部变量覆盖同名的全局变量
using Jill::fetch;
cin >> fetch;
cout << fetch;

jack::pal = 3;
Jill::pal = 3;//不同的标识符,表示不同的内存单元

using 编译命令和using 声明
局部作用
using namespace Jill;
Hill Thrill;//Jill::Hill Thrill;

std::cin >> a;
std::cout << b;

or

using std::cin;
using std::cout;
cin >>
cout<<

名称空间可以嵌套
namespace a{
	namespace B{

	}
}
a::B::...

//未命名的名称空间
namespace {
	..
}//潜在作用域为从声明点到结尾


/////////////////////////////////////////////////////////
cin.eof();//true , false;

typedef typename aliasName;
double prices = {...};
for (double x : prices)
	body


关系运算符
x+3 < y-2;
关系运算符的优先级比算术运算符低

前缀运算符从右到左的结合规则
*++pt;//*(++pt)
++*pt//== ++(*pt)

逗号//优先级最低
cata = 17,240;//17
cata = (17,240)//240
(cata = 17),240//17
/////////////////////////////////////////////////////////
vector//动态数组
#include<vector>//使用vector必须使用的头文件
vector<int> vi;
int n;
cin >> n;
vector<double> vd(n);

vector<typename> vt(n_elem);//vt是一个vector对象,可存储n_elem个类型为typename的元素
n_elem可以是整型变量或常量


array
#include <array>
array对象长度固定,用栈(静态内存分配)
array<typename,n_elem>arr;创建一个名为arr的array对象,包含n_elem个类型为typename 的元素
n_elem不能是变量
访问:和数组一样
扩展:a2[-2] = 0.4//*(a2-2) = 0.4
a2.at(1) = 12.36//a2[1] = 12.56;

////////////////////////////////////////////////////////
struct ind{
	int year;

};
ind s1,s2,s3;
s1.year = 23;;
ind * wp = &s1;
wp -> year = 1999;
ind triio[3];
(triio+1) -> year = 1235;

创建指针数组
const ind * arp[3] = {&s1,&s2,&s3};
arp[1] -> year

///********************************指针和自由存储空间**********************************/
//
#include<iostream>
#include<string>
using namespace std;
int main()
{

	//使用常规变量时,值是指定的量,地址为派生量
	//存储数据时,地址为指定的量,值为派生量
	
	using namespace std;
	int a = 0;
	int updates = 6;
	int * p_updates;
	p_updates = &updates;
	int * u_art = &a;//指针初始化///分配了储存地址的内存,但不会分配用来存储指针所指向数据的内存
	
	int* p1,p2;///p1为指针,p2为int变量
	///p_updates的类型是指向int的指针
	///在对指针进行解引用*时,必须将指针初始化为一个确定的、适当的地址
	int* pt;
	pt = (int*)0xB8000000;///pt = 0xB8000000不匹配,需要强制类型转换(int*)
	
	///使用new来动态分配内存
	int* pj = new int;	
	typename * pointer_name = new typeName;
						/*new int 告诉程序需要适合存储int的内存,
						new根据类型来确定需要多少字节的内存,
						找到这样的内存空间并返回其地址给pj*/
	
	delete pj;//不要释放已经释放的内存块
	
	int nights = 1205;
	int *pg = new int;
	*pg = nights;
	cout << "nights value = " << nights << endl;
	
	delete pg;///delete用来释放new分配的内存
	
	///使用new创建动态数组
	int * psome = new int [10];//get a block of 10 ints
								//第一个元素的地址被赋给psome指针
	delete [] psome;//释放new创建的数组//括号表示释放的是整个数组而不仅仅是指针指向的元素
	typename * pointer_name = new typename[num];
	double * p3 = new double[3];
	p3[0] = 0.67;
	p3[1] = 0.58;
	delete [] p3;
	//p3 + 1 ==> 指向的是p3[1]的地址
	//指针变量+1后,其值等于它所指向类型的字节数
	double *pw = new double[6];
	//pw比pw+1小8
	//可以修改指针的值 pw = pw + 1//但是数组名是常量
	
	double wages[3] = {3.5,65.5,89.56};
	sizeof(wages)//==> 24
	double * pw = wages;
	sizeof(pw);//==> 4
	
	short tell[10];
	//tell 和 &tell 的值相同
	//tell(第一个元素的地址) 和 &tell[0]相同,是一个2Bytes内存块的地址
	//&tell指的是整个array的地址,是一个20Bytes内存块的地址
	//tell + 1 ;地址值+2
	//&tell + 1 ;地址值+20
	//tell是一个short指针(*short)//&tell 是short数组的指针(short(*)[20])
	short (*pas) [20] = &tell;
	//pas先与[20]结合,导致pas是一个short指针数组,包含20个元素;*pas与tell等价
	
	动态lianbian
	int size;
	cin >> size;
	int * pz = new int [size];
	delete [] pz;
	
	const char * bird = "will";//"will"表示字符串的地址//const用bird访问字符串但不可修改
	
	//new 创造动态结构
	inflatable * ps = new inflatable;//足以存储inflatable结构的一块内存地址赋给ps
	
	struct things
	{
		int good;
		int bad;
	};
	things grubnose = {3,45};
	things * pt = &grubnose;
	grubnose.good == pt->good//->运算符用于指针
	
	//////////////////////
	自动存储
	自动变量是局部变量,作用域为包含它的代码块
	静态存储
	static double d = 53.65;
	存在于程序的整个生命周期
	动态存储
	new delete 管理一个内存池堆,数据的生命不受程序和函数的限制,


	cin.get();
	return 0;
}

/********************************枚举enum***********************************/
#include<iostream>
#include<string>
using namespace std;
int main()
{
	///创建符号常量代替const
	enum spectrum {red,orange,yellow,green};///red...为符号常量,它们对应的整数值0~7,这些常量称为
	spectrum band;
	band = orange;///只有4个可能的值,band=5622错误把非enum值赋给enum变量视为错误
	///枚举量是整型,可提升至int类型,反之不行eg. band=3错误
	int rd;
	rd = band + 4;//correct
	///band = red + orange;///错误,red+orange计算时强制类型转化为int,int不可赋值给band
	band = spectrum(3);//typecast 3 to type spectrum

	enum bits{one = 1,two = 2,four=4,eight,nig=2};///eight = 5,默认大1//可以有多个值相同的变量
	cin.get();
	return 0;
}
/********************************共用体union***********************************/
#include<iostream>
#include<string>
using namespace std;
int main()
{
	union one4all
	{
		int int_val;
		long long_val;
		double double_val;
	};
	one4all pa;
	pa.double_val = 2.36;///store a double
	pa.long_val= 12352;///store a long, double is lost

	struct widget 
	{
		char brand[20];
		int type;
		union id
		{
			long id_num;
			char id_char[20];
		}id_val;
	};
	widget price;
	if (price.type == 1)
		cin >> price.id_val.id_num;
	else 
		cin >> price.id_val.id_char;
	
	///匿名共用体
	struct widget 
	{
		char brand[20];
		int type;
		union //没有名称,其成员位于相同地址处的变量,每次只有一个成员是当前成员
		{
			long id_num;
			char id_char[20];//此时id_num和id_char被视为price的两个成员
		};
	};
	
	cin.get();
	return 0;
}
///********************************结构体***********************************/
#include<iostream>
#include<string>
using namespace std;
struct inflatable ///外部声明可以被后面任何函数调用
	{
		char name[20];
		float volume;
		double price;
	};//勿漏分号,结束结构声明
int main()
{
	using namespace std;
	///结构
	struct inflatable ///局部声明只能用在一个函数中
	{
		char name[20];
		float volume;
		double price;
	};//勿漏分号,结束结构声明
	inflatable hat;
	inflatable woopie;
	inflatable mainframe;

	inflatable guest = 
	{
		"Glorious Gloria",
		1.85,
		26.35
	};///guest is a structure of type inflatable
	inflatable pal =
	{
		"Ajir",
		2.36,///逗号隔开
		2.685
	};
	
	///inflatable duck {"dsf",2.365,56.0};(=)可以被省略
	
	inflatable mayor={};///各个成员每个字节都被初始化为零
	
	cout << "Expand your guest list with" << guest.name;
	cout << "and" << pal.name << "!" << endl;
	
	inflatable choice;
	choice = pal;///成员赋值有效
	struct perks 
	{
		int key;
		char car[12];
	}mr_simth,ms_jones;///同时完成定义结构和创建结构变量
	
	struct 
	{
		int x;
		int y;
	}position;///省略结构名称,同时定义一种结构类型和其变量
	
	//结构数组
	inflatable gifts[20];///array of 100 inflatable structures
	///gifts是一个inflatable数组,每个元素都是inflatable 对象
	cin >> gifts[0].price;
	cout << gifts[99].price << endl;
	
	inflatable gue[2] = //initializing an array of structs
	{
		{"dsf",1.32,25.325},//first structure in array
		{"sdf",5.23,2.69}//second structure in array
	};
	//结构中的位字段
	struct tor
	{
		unsigned int sn : 4;///4bit for sn value
		unsigned int : 4;///
		bool goodIn : 1;///valid input 1 bit
	};
	cin.get();
	return 0;
}
///**********************************string********************************/

	string str;
	const int Aside = 20;
	char char1[Aside];
	
	cout << strlen(char1)<<endl<<str.size()<<endl;
	cin.getline(char1,20);
	cout << "you enter the"<<char1<<endl;
	getline(cin,str);
	///打印)"
	//cout << R"+* ("(Who wouldn't?)",shewhispered.)+*" << endl;
	
	char ch = 'A';
	int i = ch;
	cout.put(ch);
	cout<< ch<<i<<"  some thing"<< endl;
	
	enum color{
		read,green=5,blue
	}c;
	
	cin.get();

//refister存储类,只用于需要快速访问的变量
//static存储类,表示编译器在程序的生命周期内保持局部变量的存在,不会离开作用域就销毁和创建
//extern存储类,提供一个全局变量的引用,全局变量对所有程序文件是可见的,在其他文件中使用extern来得到已定义的变量或函数的引用
///**mutable存储类,允许对象的成员代替常量???
//字符串#include<string>
//cin.getline(charr,20);grtline(cin,str);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
命名空间
Piscine【版本名】::wanda;
Microflop::wanda();
using namespace std;

赋值从右向左

int chest = 42;
int waist = 0x42;
int inseam = 042;

默认情况下,cout显示的是十进制
	cout << chest<< waist <<inseam;
	cout<<hex;修改cout显示整数的方式
	cout<<oct;
	cout<<chest
	cin >> ch;

	cout<< '$';//'$'的ASCII码
	cout.put('$');//打印字符'$'
	做为常规字符
	
	1.0e6
	strlen(name1) strlen只可计算可见字符
	sizeof() 计算数组大小
	cin.getline(name,20);每次读取一行,换行符来确定行尾,不保存换行符,储存字符串时用空字符来替换换行符
	cin.get(name,ArSize)
	cin.get(name2,arAsize)//上一个输入队列里的换行符被读取
	
	cin.get(name,ArSize)
	cin.get();
	cin.get(name2,AeSize)
	or
	cin.get(name,ArSize).get()


	String str;
	getline(cin,str)
	
	R"+*()+*" -> "(Who woulen't it)"
	///////////////////////////////////////////////////

cin是C++的标准输入流,其本身是一个对象,并不存在返回值的概念。
不过经常会有类似于
while(cin>>a)
的调用,这里并不是cin的返回值,而是>>操作重载函数
istream& operator>>(istream&, T &);的返回值,其中第二个参数由cin>>后续参数类型决定。
其返回值类型为istream&类型,大多数情况下其返回值为cin本身(非0值),只有当遇到EOF输入时,返回值为0。
输入EOF的方法,windows下输入ctrl+z, Linux下输入ctrl+d。
于是,当输入所有数据后,通过输入EOF的方法,可以退出while(cin>>a)这样的循环。
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2018-2021 Quincy
  • Visitors: | Views:

请我吃串串呗~

支付宝
微信