person.h
/**************************************
在此处进行成员属性、函数声明
自动生成4个
1、无参构造函数 对private成员初始化
2、析构函数 内存泄漏
3、拷贝构造函数 深度赋值
4、=运算符重载 深度赋值
**************************************/
#ifndef _person
#define _person
class Cat{
public:
void F();
};
class person{//抽象性
private://封装性
//const int id; //const id=1;// error c++不允许直接赋值 只允许在构造函数中赋值
int m_id;
char* m_name;
public:
static void PrintName(person * temp);
//inline 成员函数默认都是内联函数 可以不加 inline
void PrintName();
//得到函数的地址
void getAddress();
int getM_id();
/*
运算符重载:
*/
void operator=(person& temp){
this->m_id=temp.m_id;
//重新分配空间 深度赋值
this->m_name=new char[10];
strcpy(this->m_name, temp.m_name);
cout<<"运算符重载"<<endl;
}
public:
int GetId();
/*
explicit
放在构造函数前面:
表示在 实例化 赋值的时候不能隐形转化
比如: person onePerson=1;
person onePerson(1);
加了 explicit 就只会把 1 当成int
不加 如果没有 构造函数只有一个参数是int的
只有 一个参数是char * 型的 那么就会找该构造函数实例化
此时就会把 1 隐形转化
避免隐形转化在构造函数前加 explicit
*/
/*
拷贝构造函数
*/
explicit person(person& temp){
this->m_id=temp.m_id;
//重新分配空间 深度赋值
this->m_name=new char[10];
strcpy(this->m_name, temp.m_name);
cout<<"拷贝构造函数"<<endl;
}
/*
构造函数
1、没有返回值
2、函数名和类名一样
3、参数和传统函数一样
*/
explicit person();
explicit person(int id, char* name);
explicit person(char* name);
/*
析构函数
1、在对象销毁时调用
2、作用,释放内存,等
*/
~person();
/*
----------------
友元:
----------------
1、如果希望一个普通函数F中能够访问类C中的
非公有成员,可以在类C中声明普通函数F为类C的友元
class C{
//注意这个函数是全局函数 没有定义C中
friend void F();
};
void F(){
//该函数可以访问类C非公有的成员
}
2、如果希望类C2的成员函数C2::F可以访问类C1的非公有成员
可以在类C1中将类C2的成员函数C2 F声明为友元
class C2{
void F(){
//该函数可以访问类C非公有的成员
}
};
class C1{
friend void C2::F();
};
3、如果希望类C2的【所有成员函数】可以访问类C1的非公有成员
可以在类C1中将类C2的成员函数C2声明为友元
class C2{
//所有函数可以访问类C1非公有的成员
void F(){
}
};
class C1{
//类C2可以访问类C1的非公有成员
friend void C2;
};
*/
friend void test();
friend void Cat::F();
}; //注意此处的; 和c语言的struct{}; 可以进行比较
#endif _person
person.cpp
#include <string.h>
#include <iostream>
using namespace std;
#include "person.h"
/*
在此处进行函数的实现
*/
//静态函数
//调用方式: 类名::函数()
/*
声明: static void PrintName(person temp);
注意实现的时候就不需要加 static
*/
void person::PrintName(person * temp){
cout<<"temp.m_name="<<temp->m_name<<endl;
}
//this指向当前实例
//用法: this->属性名
void person::PrintName(){
cout<<"this->m_name="<<this->m_name<<endl;
}
void person::getAddress(){
cout<<"this="<<this<<endl;
}
int person::getM_id(){
return this->m_id;
}
//:id(1) 初始化常量
/*
此种方法: 构造函数名():属性名1(值1), 属性名2(值2)...
可以用于初始化常量,并且常量只能用此方法初始化
也可以初始化成员变量
此种方式不能初始化字符串
*/
person::person()//:id(1)
{
this->m_id=122;
/*
注意事项:
new 分配的内存 被所有person类型的 对象 所共享
只要有一个person类型的对象delete new分配的内存后
其它person类型的对象也就不能访问该内存了
*/
this->m_name = new char[10];
strcpy(m_name, "tangtao");
}
person::person(int id, char* name)//:id(id) //可以通过参数初始化const
{
//this->id = 1;
this->m_id = id;
this->m_name = new char[10];
strcpy(this->m_name, name);
}
person::person(char* name){
this->m_name = new char[10];
strcpy(this->m_name, name);
}
//释放内存 防止内存泄漏
person::~person(){
cout<<"delete............"<<endl;
if(this->m_name!=NULL){
delete this->m_name;
this->m_name = NULL;
}
}
int person::GetId()
{
return this->m_id;
}
void Cat::F(){
person onePerson(12, "tangtao");
cout<<"类2访问类1的非共有的成员=="<<onePerson.m_name<<endl;
}
Test.cpp
#include <iostream>
using namespace std;
#include "person.h"
#include <stdio.h>
#include "person.h"
/*
类是对象的抽象
对象是类的具体实现
*/
/*class person{//抽象性
private://封装性
int m_id;
public:
char m_name[10];
//静态函数
//调用方式: 类名::函数()
static void PrintName(person temp){
cout<<"temp.m_name="<<temp.m_name<<endl;
}
//this指向当前实例
//用法: this->属性名
void PrintName(){
cout<<"this.m_name="<<this->m_name<<endl;
}
}; //注意此处的; 和c语言的struct{}; 可以进行比较
int main(){
person onePerson={1, "tangtao"}; //什么是实例化 分配内存的过程,也就是对象
//onePerson.m_id=12; //private
strcpy(onePerson.m_name, "itao");
//PrintName(onePerson);
//onePerson.PrintName();
person::PrintName(onePerson);
onePerson.PrintName();
cout<<onePerson.m_name<<endl;
return 0;
}
*/
int test1(){
//person onePerson; //无参的构造函数实例化对象
//什么是实例化 分配内存的过程,也就是对象
person onePerson(21, "itao");
//实例化有参数的构造函数
//onePerson.m_id=12; //private
//strcpy(onePerson.m_name, "itao");
//PrintName(onePerson);
//onePerson.PrintName();
//person::PrintName(&onePerson);
//onePerson.PrintName();
//cout<<"m_id="<<onePerson.getM_id()<<endl;
//cout<<"person.size="<<sizeof(onePerson)<<endl;
//cout<<onePerson.m_name<<endl;
//onePerson.getAddress();
//cout<<"temp="<<&onePerson<<endl;
/*
深度赋值:
就是取成员的具体内容,
而不是简单的指针赋值
牵扯到两个概念:
拷贝构造函数和运算符重载
默认:
浅赋值 就是指针赋值
*/
//在初始化的同时赋值 才会执行拷贝构造函数
person otherPerson = onePerson;
//初始化后赋值 执行运算符重载
person otherPerson2;
otherPerson2=onePerson;
//运算符重载与上相同
//otherPerson.operator =(onePerson);
/*
特别注意:
*/
person otherPerson3=person(12, "asd");
//等价于 person otherPerson3(12, "asd");
person otherPerson4;
otherPerson4=person(12, "asd");
/*
自动生成拷贝构造函数
*/
person otherPerson5="jack";
//cout<<"otherPerson5="<<&otherPerson5<<endl;
person otherPerson6;
otherPerson6 = person("jack");
//cout<<"地址"<<&onePerson<<endl;
//cout<<"地址"<<&otherPerson4<<endl;
return 0;
}
int test2(){
/*
const int:
表示 是常量
const int *:
表示存放的是常量的地址,即指向常量
const int * const
或者
int const * const
表示指向常量的常量指针
*/
const int i=1; //i不能被修改
const int * pI1=&i; //不能通过pI1修改i
const int * const pI2=&i; //不能通过pI2修改i 并且pI2也不能被修改
//等价于==
int const * const pI3=&i;
/*
函数后面加const
void PrintName()const;
void PrintName()const{
}
作用:
在成员函数中用const锁定实例
该函数内不能修改成员变量和常量
*/
return 0;
}
//该函数为友元函数
//友元函数中能访问类中非共有的成员
void test(){
person onePerson(11, "itao");
cout<<"友元函数=="<<onePerson.m_name<<endl;
}
int main(){
//person onePerson(11, "itao");
//cout<<onePerson.GetId()<<endl;
//test();
Cat oneCat;
oneCat.F();
return 0;
}