1.模板
#include <iostream>
using namespace std;
template<class T>
void Swap(T &a,T &b)
{
a = a + b;
b = a - b;
a = a - b;
}
int main()
{
double a = 1.5456456456,b = 2.5456546546;
printf("%lf %lf\n",a,b);
Swap(a,b);
printf("%lf %lf\n",a,b);
return 0;
}
2.引用
struct Base
{
int x;
int y;
Base(int x,int y)
{
this->x = x;
this->y = y;
}
};
void PrintByPoint(Base* pb)
{
printf("%d %d\n",pb->x,pb->y);
pb = (Base*)0x123456;
//为所欲为...
}
void PrintByRef(Base& refb,Base* pb)
{
printf("%d %d\n",refb.x,refb.y);
Base b1(21,31);
//&refb = b1; //引用不能重新赋值
refb = b1; //这个不是重新赋值,这个是把b1的值赋给refb代表的对象
printf("%d %d\n",pb->x,pb->y);
}
为了避免出现这种情况,可以将refb声明为常量,不可修改:
void PrintByRef(const Base& refb)
{
printf("%d %d\n",refb.x,refb.y);
Base b1(21,31);
//&refb = b1; //引用不能重新赋值
//refb = b1; //不允许
}
int main(int argc, char* argv[])
{
Base base(1,2);
PrintByRef(base,&base);
return 0;
}
总结:
- 引用类型是C++里面的类型
- 引用类型只能赋值一次,不能重新赋值
- 引用只是变量的一个别名.
- 引用可以理解成是编译器维护的一个指针,但并不占用空间(如何去理解这句话?).
- 使用引用可以像指针那样去访问、修改对象的内容,但更加安全.
const加在类型名前和变量名前的区别?
const是用来声明一个常量的,当你不想让一个值被改变时就用const, const int max && int const max 是没有区别的,都可以。
涉及到指针的情况:
int b=100;
const int * a=&b;[1]
int const *a=&b; [2]
int* const a=&b; [3]
const int* const a =&b; [4]
如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。因此,[1]和[2]的情况相同,都是指针所指向的内容为常量(const放在变量声明符的位置无关),这种情况下不允许对内容进行更改操作,如不能*a = 3 ;[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;[4]为指针本身和指向的内容均为常量。
3.友元函数
class Person
{
private:
int x;
int y;
public:
Person(int x,int y)
{
this->x = x;
this->y = y;
}
//声明友元函数
friend void Print(const Person& refPer);
};
void Print(const Person& refPer)
{
printf("%d\n",refPer.x);
printf("%d\n",refPer.y);
}
int main(int argc, char* argv[])
{
Person p(1,2);
Print(p);
return 0;
}
什么情况下需要友元函数:
- 运算符重载的某些场合需要使用友元.
- 两个类要共享数据的时候.
友元函数和类的成员函数的区别
- 成员函数有this指针,而友元函数没有this指针
- 友元函数是不能被继承的,就像父亲的朋友未必是儿子的朋友
4.运算符重载
class Number
{
private:
int lowValue;
int highValue;
public:
Number(int lowValue,int highValue);
void Print();
Number operator++();
Number operator--();
Number operator+(const Number& p);
Number operator-(const Number& p);
Number operator*(const Number& p);
Number operator/(const Number& p);
bool operator>(const Number& p);
bool operator<(const Number& p);
bool operator==(const Number& p);
};
Number::Number(int lowValue,int highValue)
{
this->lowValue = lowValue;
this->highValue = highValue;
}
void Number::Print()
{
printf("%d\n",lowValue);
printf("%d\n",highValue);
}
Number Number::operator++()
{
lowValue++;
highValue++;
return *this;
}
Number Number::operator--()
{
lowValue--;
highValue--;
return *this;
}
Number Number::operator+(const Number& p)
{
this->highValue = this->highValue + p.highValue;
this->lowValue = this->lowValue + p.lowValue;
return *this;
}
Number Number::operator-(const Number& p)
{
this->highValue = this->highValue - p.highValue;
this->lowValue = this->lowValue - p.lowValue;
return *this;
}
Number Number::operator*(const Number& p)
{
this->highValue = this->highValue * p.highValue;
this->lowValue = this->lowValue * p.lowValue;
return *this;
}
Number Number::operator/(const Number& p)
{
this->highValue = this->highValue / p.highValue;
this->lowValue = this->lowValue / p.lowValue;
return *this;
}
bool Number::operator>(const Number& p)
{
if(this->highValue > p.highValue)
{
return true;
}
return false;
}
bool Number::operator<(const Number& p)
{
if(this->highValue < p.highValue)
{
return true;
}
return false;
}
bool Number::operator==(const Number& p)
{
if(this->highValue == p.highValue)
{
return true;
}
return false;
}
void Test()
{
Number p(1,2),p2(3,4);
p++;
p.Print();
p--;
p.Print();
p = p+p2;
p.Print();
}
int main(int argc, char* argv[])
{
Test();
return 0;
}
对流运算符<<和>>的重载有固定的格式
为什么要声明成友元函数,参考为什么operator<<>>运算符重载一定要为友元函数呢?
friend ostream & operator<<( ostream & out,const Complex & c)
{
out << c.real << "+" << c.imag << "i"; //以"a+bi"的形式输出
return out;
}
friend istream & operator>>( istream & is,Complex & c);
总结:
- 运算符重载就是函数替换
- . :: ?: sizeof # 不能重载
- 结合上面所述,一般在以下两个场景中会用到友元函数:
- 运算符重载的某些场合需要使用友元函数;
- 两个类要共享数据的时候。
从反汇编的角度说说引用与指针的区别
首先他们在底层是一样的,上面已经说过,引用只是编译器免费维护的并且不占用空间
在底层很难看出指针与引用的区别
#include <iostream>
using namespace std;
struct Base
{
int x;
int y;
Base(int x,int y)
{
this->x = x;
this->y = y;
}
};
void PrintByPoint(Base* pb)
{
printf("%d %d\n",pb->x,pb->y);
pb = (Base*)0x123456;
}
void PrintByRef(Base& refb)
{
printf("%d %d\n",refb.x,refb.y);
Base b1(21,31);
refb = b1; //不允许
}
int main(int argc, char* argv[])
{
Base base(1,2);
PrintByPoint(&base);
PrintByRef(base);
return 0;
}
先看函数调用传参情况,完全一样
参数为指针
参数为引用
可以看到是完全一样的,如何非要区分指针和引用,只有看到这种反汇编才能确定它是指针,因为引用是无法修改的,而指针是可以修改的。