C++笔记8.23

静态对象
全局变量、本地变量
static: 持久存储(在哪里)
访问受局限(谁能看到你)

static本地变量就是全局变量

全局变量static: 只在这个.c文件里有效
本地变量static: 这个本地变量具有持久存储, 无论是否离开,本地变量都是保存着这个值的.(其实static本地变量就是全局变量)
函数static: 这个函数只能在.c文件里被访问,.c以外是无法访问的.
这里写图片描述

说明:(1). File1: global是一个全局变量,
在File2: 可以直接用extern来使用g_global
(2). File1: static int s_local, 表明s_local只能在File1文件
中使用, 就算在File2中使用static, 也只能骗过编译器,
但骗不过linker.
为何骗不过linker: s_local只能在File1中使用, File2中
extern int s_local要使用File1中的s_local, 两者相矛
盾,所以链接失败.
(3). static void hidden() 只能在File1文件中使用, 不能在File2文件中使用.
全局变量的初始化
X global_x(12,34);
main不是第一个被调用的,先调ctor
程序结束时,析构被执行

类的成员是static
C语言有两种persistent的东西:全局变量(包括静态的本地变量)/malloc出来的东西, 即离开了函数还在的东西
不随着对象不同而不同:persistent,借助static来做
static member:hidden+persistent,是整个类的东西
静态成员变量:在类的所有对象中都一样,且值保持一致

//extern int i;   不知道位置
class A {
public:
	A() { i = 0; }
	void print() { cout << i << endl; }
	void set(int ii) { i = ii; }
private:
	static int i; //无法编译,这个静态的本地变量在全局,但是这是声明,并没有这个i的位置,写在class里的所有东西都是声明,需加上下面一句
};
int A::i; //需写在cpp里,一定需要对应的cpp文件,否则无处安身 *
int main() {
	A a, b;
	a.set(10);
	b.print();
	return 0;
}

inline的body可以放在.h文件中,不需要.cpp文件
*改成static int A:: i; 报错,它意味着只有这个cpp文件可以访问,但是类的静态成员可能在外部被访问,int A::i(20);是可以的
类里面说A():i(20){} 是错误的,因为A的i是一个静态成员,只能在自己定义的地方被初始化,不能在初始化列表里
void set(int i){this->i = i;} 是正确的
如果静态成员变量是public的,main中可以用cout<<a.i<<endl;
也可以用cout<<A::i<<endl;

静态成员函数:
对于C++来说,所有的函数本来就是全局的,函数不跟着对象走

public:
	
	static void say(int ii) { cout << i << endl; }
main:
a.say(0);
A::say(0);//ok

加上private:
int k;
然后say去访问k是不行的,静态的函数只能够访问静态的成员变量
同样say{cout<i}是不行的,this只能用于访问非静态函数,静态函数与对象的存在与否无关

运算符重载基本规则
写函数改变运算符的行为
运算符重载细则

不能自己创造运算符来重载,**
只能对一个类和枚举的类型来做
重载的运算符保持原有的操作数个数,保持优先级
就是把运算符的运算用自己写的函数来表达
重载乘号:operator *()
它可以做成员函数
const String String: :operator +(const String& that);
也可以做全局函数
const Striing operator+ (const String& r,const String& l);
作为成员函数,this是第一个参数

class Integer
{
public:
Integer(int n = 0):i(n) {}
const Integer operator+(const Integer& n) const
{ 
return Integer(i+n.i);  //不修改加数的值,会生成一个新的类,然后返回这个类的对象
}
……
private:
int i;
};

函数前面必须是const,否则可以做左值,例如a+b=6
Interger x(1),y(5),z; x + y ===>x.operator+(y) //operator+看作一个函数整体,接受y传入
运算符左边那个算子叫receiver,决定用哪个加
如果编译器看到inline,然后某个对象没有被使用,仅仅是为了传参数,会直接优化,没有拷贝构造
z=x+3;会用构造函数把3构造成一个对象
z=3+y;需要类把自己的对象变成一个int型,编译无法通过
z=x+3.5 不行,double到int不能自动转换,除非类里面就是double,但是int可以自动转换为double
一元参数,例如对自己取负,实质上是制造出一个新的对象

const Integer operator-() const { return Integer(-i); }
作为全局函数,需要把两个算子都写进去

const Integer operator+(
const Integer& rhs, 
const Integer& 1hs);
Integer x,y;
x + y ===> operator+(x,y);

此时在两个参数上都可以做类型转换

class Integer
{
friend const Integer operator+ (
const Integer& lhs, 
const Integer& rhs);
……
};
const Integer operator+ (
const Integer& lhs, 
const Integer& rhs)
{
return Integer(lhs.i + rhs.i);
}

作为全局函数时,z=3+y 是可以的,把3变成那个类的对象
z=3+7同样可以,把结果10直接构造成类的值
到底是选择成员对象还是非成员
tips:
一元的应该做成成员的
而= () [] -> ->*必须是成员的
赋值操作符应该是
其他二元的等全部做成非成员的

运算符重载-原型
函数的原型是怎样的,怎么传入传出
赋值的,参数是整数怎么做
传进去的参数肯定是引用,看运算符会不会修改算子
++,–,+=,-=会修改算子,不能用const
返回值看是对自己做修改还是创造了一个新的对象,以及返回的可以不可以做左值,加法就必须做const,赋值是修改自己,函数后面不能有const,但是返回后也应该可以修改,所以返回一个reference,并且后续也可以做左值
index:参数是整数 a[6],可以做左值,返回reference
大于小于返回布尔量

+-*/%^&|~const T operatorX(const T& I, const T& r) const;

! && || < <= == >= >bool operatorX(const T& I, const T& r) const;
[]
—T& T::operator[](int index);
class Integer
{
public:const Integer& operator++(); //prefix++
const Integer operator++(int); //postfix++
const Integer& operator--(); //prefix--
const Integer operator++(int); //postfix--
};

加加在前面的没有参数,返回一个引用,++a返回a加了之后的结果,就是当时的那个a,返回引用就可以,但是都是const,禁止做左值,a++=6
加加在后面返回一个新对象,返回加以前的结果,但是返回的已经不是以前的那个a了,
int不会起作用,只是让编译器区分

const Integer& Integer::operator++(){
	*this += 1;
	return *this; //this是指针,加个星之后变成对象,且保证不会被修改
const Integer Integer::operator++(int){
	Integer old(*this);//拷贝构造,用一个对象制造一个新的对象
	++(*this);//用第一个定义第二个
	return old; //不能return reference,因为是本地变量的reference,离开函数后reference就不存在,所以需要返回一个新的对象
}
++x;//calls x.operator++()
x++;//calls x.operator++(0)//这两个是重载函数
class Integer{
	public:
	..
	bool operator==(const Integer& rhs) const;
	bool operator!=(const Integer& rhs) const;
	bool operator<(const Integer& rhs) const;
	bool operator>(const Integer& rhs) const;
	bool operator<=(const Integer& rhs) const;
	bool operator>=(const Integer& rhs) const;
};
bool Integer::operator==(const Integer& rhs) const{
	return i == rhs.i;
}
bool Integer::operator!=(const Integer& rhs) const{
	return !(*this == rhs.i);
}
bool Integer::operator<(const Integer& rhs) const{
	return i < rhs.i;
}
bool Integer::operator>(const Integer& rhs) const{
	return  rhs<*this;
}
bool Integer::operator<=(const Integer& rhs) const{
	return  !(rhs<*this);
}
bool Integer::operator>=(const Integer& rhs) const{
	return  !(*this<rhs);
}

只定义了两个原函数,等于和小于,只有这两个深入到this和rhs里面的i
所有上面函数都做成inline,不担心性能损失

[]: index
只用作成员的,用于类表达一种容器的概念
Vector v(100);
v[10]=45; 返回成员类型的引用,可以做左值

class Vector {
public:
	Vector(int size) :m_size(size) {
		m_array = new int[size];
	}
	~Vector() { delete m_array; }
	int& operator[](int index) { return m_array[index]; }
private:
	int m_size;
	int *m_array; //可以扩展
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值