- 将“引用”作为函数返回值类型的格式、好处和需要遵守的规则
函数格式:类型标识符(如int)&函数名(参数列表){函数体}
好处:返回的值不用创建副本。
注意事项:
1. 不能返回局部变量的引用。因为局部变量的引用在函数返回时会被销毁,使得引用指向不明,程序进入未知状态。
2. 不能返回函数内部new分配的内存的引用。被函数返回的引用只是一个临时变量,而没有被赋予一个实际变量,那么这个引用所指向的内存没法释放,会造成内存泄漏。
3. 可以返回类成员的引用,但是最好是const。因为类成员一般是封装隐藏的,不能被修改。
1.新特性
bool类型
bool flag=0;
if(flag)
{
//to do
}
else
{
//to do
}
2.随用随定义变量
3.C++的I/O方式
cout的语法形式
cout>>x>>endl;(endl相当于C语言中的/n)
cout<<”x+y=”<
namespace A namespace B
{ {
int x=0; int x=2;
void fun1(); void fun1();
void fun2(); void fun3();
} }
cout<
int *p=new int [1000];
if(NULL==p)
{
//内存分配失败
}
delete p; //释放内存
p=NULL; //将指针p置空
类(类名最好能看出类的功能)
class Dog //类名(关键字)
{
char name[20]; //数据成员(属性)
int age;
int type;
void shout(); //成员函数(方法)
void run();
};
目的不同抽象出的信息不同。
访问限定符:public,private,protected
class TV
{
public:
char name[20]; //希望暴露出来的
int type;
void changeVol();
void power();
private:
电阻调节; //希望隐藏的
像素配色;
};
对象:具体事物
对象实例化
从栈实例化对象:(引用上面的类TV)
int main()
{
TV tv;
TV tv[20];
return 0;
}
从堆实例化对象:
int main()
{
TV *p=new TV();
TV *q=new TV[20];
//to do something
delete p;
delete []q;
return 0;
}
对象成员访问
单一:
tv.type=0; tv.changeVol(); (栈访问)
p->type=0; p->changeVol(); (堆访问)
数组:
int main()
{
TV *q=new TV[20];
for(i=0;i<20;i++)
{
q[i]->type=0;
q[i]->changeVol();
}
delete []q;
q=NULL;
return 0;
}
操作频繁且复杂的数据类型: char 数组(类型)
string类型
#include<iostream>
#include<string>
using namespace std;
int main()
{
string name=”Zhang san”;
string hobby(“football”); //将football初始化给hobby:
cout<<name<<hobby<<endl;
return 0;
}
string s1; //s1为空串
string s2(“abc”) //s2被初始化为abc
string s3(s2) //s3初始化为s2的一个副本
string s4(n,’c’) //s4初始化为n个c
string s=”hello”+”world”; //这种表达式错误,字符串之间不能直接相接
string s1=”a”+s2; //合法
封装的好处
class Student
{
public:
void set_age(_age) //这也称为类内定义
{
if(_age>0&&_age<100) //通过封装限制了age的设置条件
{
age=_age;
}
else
.....
}
void get_age()
{
return age;
}
private:
string name;
int age;
...
};
class Car
{
public:
get_Wheelcount() //封装使得这个函数是只读形式
{return Wheelcount;}
private:
int Wheelcount;
};
类内定义与内联函数 类内定义的函数编译器自动定义为内联函数
类外定义
同文件类外定义:
class Car
{
public:
void run();
void stop();
void changespeed();
};
void Car::run(){…};
void Car::stop(){…};
void Car::changespeed(){…};
分文件类外定义:
编写一个头文件Car.h
class Car
{
public:
void run();
void stop();
void changespeed();
};
编写一个源文件Car.cpp
#include”Car.cpp”
void Car::run(){...};
void Car::stop(){...};
void Car::changespeed(){...};
内存分区
栈区 int x=0;int *p=NULL;
堆区 int *p=new int[20];
全局区 存储全局变量和静态变量
常量区 string str=”hello”;
代码区 存储逻辑代码的二进制
对象初始化
构造函数
特点
在对象实例化时被自动调用;构造函数与类同名;构造函数没有返回值;构造函数可以有多个重载形式;实例化对象时仅用到一个构造函数;当用户没有定义构造函数时,编译器自动生成一个构造函数。
无参构造函数
class Student
{
public:
Student()
{m_strName=”jim”;}
private:
string m_strName;
};
有参构造函数
class Student
{
public:
Student(string _name)
{m_strName=_name;}
private:
string m_strName;
};
重载构造函数
class Student
{
public:
Student()
{m_strName=”jim”;}
Student(string _name)
{m_strName=_name;}
private:
string m_strName;
};
初始化列表
class Student
{
public:
Student():m_strName(“Jim”),m_iAge(15){}
private:
m_strName;
m_iAge;
};
初始化列表的特性:初始化列表先于构造函数执行;初始化函数只能用于构造函数;初始化列表可以同时初始化多个数据成员
初始化列表的重要性
class Circle
{
public:
Circle(){m_dpi=3.14} //错误 因为已经将m_dpi限定了,不能再赋值了
private:
const double m_dpi;
};
class Circle
{
public:
Circle():m_dpi(3.14){} //正确
private:
const double m_dpi;
};
拷贝构造函数
定义格式:
类名(const 类名&变量名)
class Student
{
public:
Student();
{
m_strName=”Tom”;
}
Student(const Student&stu){...};
private:
string m_strName;
};
如果没有自定义拷贝构造函数,则系统会自动生成一个默认的拷贝构造函数
当采用直接初始化或者复制初始化实例化对象时,系统自动调用拷贝构造函数
拷贝构造函数不能重载
析构函数(释放资源)
定义格式:~类名()
class Student
{
public:
Student() {m_pName=new char[20];}
~Student() {delete []m_pName;}
private:
char *m_pName;
};
如果没有自定义的析构函数,则系统自动生成;
析构函数在对象销毁时自动调用;
析构函数没有返回值和参数,也不能重载
对象的生命历程
1.申请内存->2.初始化列表->3.构造函数->4.参与运算->5.析构函数->6.释放内存
对象数组
class Coordinate
{
public:
int m_iX;
int m_iY;
};
int main()
{
Coordinate coord[3];
coord[1].m_iX=3;
Coordinate *p=new Coordinate[3];
p[0].m_iX=10; p[0]->m_iX=17;
delete []p;
p=NULL;
return 0;
}
对象成员
class Coordinate
{
public:
Coordinate(int x,int y);
private:
int m_iX;
int m_iY;
};
class Line
{
public:
Line(int x1,int y1,int x2,int y2);
private:
Coordinate m_coorA; //数据类型是Coordinate
Coordinate m_coorB;
};
Line::Line(int x1,int y1,int x2,int y2):m_coorA(x1,y1),m_coorB(x2,y2)
{
cout<<”Line”<<endl; //Line的构造函数
}
int main()
{
Line *p=new Line(2,3,4,5);
delete p;
p=NULL;
return 0;
}
浅拷贝
class Array
{
public:
Array()
{m_iCount=5;}
Array(const Array& arr)
{m_iCount=arr.iCount;}
private:
int m_iCount;
};
深拷贝
class Array
{
public:
Array()
{m_iCount=5,m_pArr=new int[m_iCount];}
Array(const Array& arr)
{m_iCount=arr.m_iCount;
m_pArr=new int[m_iCount];
for(i=0;i<m_iCount;i++)
{m_pArr[i]=arr.m_pArr[i];}}
private:
int m_iCount;
int *m_pArr;
};
对象指针
class Coordinate
{
Coordinate *p=new Coordinate;
p->m_iX=10; //(*p).m_iX=10;
p->m_iY=15; //(*p).m_iY=15;
delete p;
p=NULL;
return 0;
};