(1)struct
在C语言中,struct是结构体,只有成员变量,不能有成员方法,不可以为空,因为一旦定义为空,占的内存也为零,这样它定义变量的地址和之后的其他变量的内存地址就一样的了;而在C++中struct是类可以为空(成员变量为空,但成员方法(四个默认的方法)不为空,占的空间为1,siezof=1);struct 的默认访问属性是public
class 的默认访问属性的private
(2)this
1. this 具有常性,不能改变。普通方法声明或定义的地方,参数列表第一的要加入this;
2. 普通方法方法体内。出现使用成员变量后者成员方法是前面y要加this->;
3. 成员方法调用点加入this参数;
(3)构造函数
1、实例化一个对象的时候会会调用一个匹配的构造函数
2、如果自己未定义时,编译器会自动生成一个没有参数的构造函数(什么都不做);
3、如果自己已定义,编译器将该不会自动生成默认构造函数;
4、拷贝构造函数:用一个以初始化的对象实例化一个正在产生的对象所使用的构造方法,如果自己并没有实现自己的拷贝构造函数,编译器会生成一个默认的拷贝构造函数,其只是简单的内存的拷贝(浅拷贝),如果是指针的话,将拷贝指针的地址。要预防浅拷贝,必须用对象的引用并加上const ,这样做的目的是防止在传入对象是有重新运行构造函数,这样会导致死循环,传入引用将不会有对象的构造。
(4)重载赋值运算符=
1、对象之间进行赋值的时候会自动调用=运算符,如果没有自己没有重载,编译器会自动生成浅拷贝赋值;
2、要预防内存泄露,在赋值之前必须将要赋值对象指向的内存释放掉;
3、要防止自赋值,如果是自己给自己赋值这返回自己(*this);
4、要防止浅拷贝;
(5)析构函数
1、在·对象生存期满了之后,自动调用析构函数。
2、如果自己没有自定义析构函数,编译器会自动生成一个默认的析构函数;
3、析构函数值只能释放在栈上保存的变量,new和Malloc开辟的在堆上的内存需要手动释放。
(6)面向对象的四大特征:抽象、继承、封装、多态
(7)static
1、 静态的成员变量需要在类外进行初始化 类型名 类名::变量名=初始化值;
2、静态成员变量:存储数据段,整个类只有一份,访问不依赖于对象(this),依靠类的作用域,初始化在类外进行;
3、静态成员方法:访问不依赖于对象(this),可以直接通过作用域访问,在静态成员方法中不能使用非静态的成员,因为静态成员方法没有传入this指针,非静态的成员方法中可以访问静态的成员。
(8)临时对象
1、临时对象:没有名字的对象 生存周期:当前语句结束 如果临时对象被引用,他的生存周期会被提升到该引用的生存周期
2、隐式产生临时对象:不使用类型名产生临时对象,依赖需要转化的对象的类型推导出临时对象的类型 具有const属性
3、显示产生临时对象:使用类型名产生临时对象
4、内置类型产生的临时量 无论显示函数隐式产生都是常量
const int &c = fun();
const int &d = (int)fun();
5、
class Person
{
private:
char *_name;
char *_sex;
int _age;
static unsigned int _personNum;
public:
Person(char *name = "zhangsan", char *sex = "nan", int age = 20)
{
cout << "Person(char *name = 'zhangsan', char *sex = 'nan', int age = 20)" << endl;
if (NULL == name || NULL == sex)
{
cout << "agc error" << endl;
return;
}
_name = new char[strlen(name) + 1];
_sex = new char[strlen(sex) + 1];
strcpy_s(_name, strlen(name) + 1, name);
strcpy_s(_sex, strlen(sex) + 1, sex);
_age = age;
_personNum++;
}
//一定要传引用
Person(const Person& src)
{
cout << "Person(const Person& src)" << endl;
//防止浅拷贝
_name = new char[strlen(src._name) + 1];
_sex = new char[strlen(src._sex) + 1];
strcpy_s(_name, strlen(src._name) + 1, src._name);
strcpy_s(_sex, strlen(src._sex) + 1, src._sex);
_age = src._age;
_personNum++;
}
Person& operator=(const Person& src)
{
cout << "Person& operator=(const Person& src)" << endl;
//防止自赋值
if (this == &src)
{
return *this;
}
//防止内存泄漏
delete[]_name;
delete[]_sex;
//防止浅拷贝
_name = new char[strlen(src._name) + 1];
_sex = new char[strlen(src._sex) + 1];
strcpy_s(_name, strlen(src._name) + 1, src._name);
strcpy_s(_sex, strlen(src._sex) + 1, src._sex);
_age = src._age;
}
~Person()
{
cout << "~Person()" << endl;
//防止内存泄露
delete[]_name;
delete[]_sex;
_personNum--;
}
void show()const;
void setAge(Person& per, int num)
{
if (0){}
_age = num;
}
static void showNum()
{
cout << "person num:" << /*this->_personNum */ Person::_personNum << endl;
}
};
//静态的成员变量需要在类外进行初始化
unsigned int Person::_personNum = 0;
//在类内的成员方法默认是inline,在类外就不默认了,因为inline的作用域为本文件。
void Person::show(/* const Person * const this */)const
{
//this = NULL;
//this->_age = 10000;
cout << "name:" << this->_name << endl;
cout << "sex:" << _sex << endl;
cout << "age:" << _age << endl;
}
int fun()
{
return 10;
}
#if 0
int main()
{
/*
对象的生存周期
*/
Person p1("lisi");
Person p2(p1);
p2 = p1;
Person* p3 = new Person();
*p3 = p1;
delete p3;
Person p4 = "wangwu";//先构造临时对象 临时对象构造p4 析构临时对象----》直接构造
//隐式产生临时对象
p2 = "wangwu";//先用“wangwu”构造一个临时对象 用临时对象赋值给p2 析构临时对象
/*const Perosn& = const Person*/
const int a = 10;
const int &b = a;
//显示产生临时对象
p1 = (Person)"wangmazi";
Person &p6 = (Person)"xiaoming";
/*
自定义类型
临时对象:没有名字的对象 生存周期:当前语句结束 如果临时对象被引用,他的生存周期会被提升到该引用的生存周期
隐式产生临时对象:不使用类型名产生临时对象,依赖需要转化的对象的类型推导出临时对象的类型 具有const属性
显示产生临时对象:使用类型名产生临时对象
*/
Person p5 = "aa";
const int &c = fun();
const int &d = (int)fun();
/*
内置类型产生的临时量 无论显示函数隐式产生都是常量
*/
return 0;
}
#endif
Person fun(Person& p)//函数传递参数尽可能传递& / * 接受返回对象 尽可能使用新产生的对象接受
{
//Person p2 = p;//一般不要在局部产生对象
return "zhangsan";
/*
构造临时量 用临时量构造返回值临时量 析构临时量----》直接构造返回值临时量
返回值临时量拷贝构造p3 析构返回值临时量 ---》直接构造p3
*/
}
/*
(9)函数的默认值参数:
在函数声或定义时初始化,就是给函数参数给默认值;形参给默认值是从左向右,实参是从左向右对应(在同一个文件里,一个形参只允许赋一次值,不能重复,相同的值也不行)
(10)C++的符号是由函数名和参数列表
(11)函数重载的条件:
①函数名相同;
②参数列表不同
③作用域相同
(12)两个内置类型的数据进行运算必须要两个数据类型相同才行;