4.类和对象
//C++面向对象的三大特性:封装、继承、多态
//三种访问权限
//公共 public 类内可以访问 类外可以访问
//保护 protected 类内可以访问 类外不可以访问
//私有 private 类内可以访问 类外不可以访问
//struct和class区别:
// struct默认权限为公共,class为私有
//成员属性设置成私有:可以控制读写权限,写入时检查合法性
//对象的初始化和清理:
// 构造函数和析构函数
// 构造函数的分类及调用
// 分类:
// 参数:有参和无参
// 类型:普通构造和拷贝构造
// 调用方式:
// 1.括号法
// 2.显示法
// 3.隐式转换法
//拷贝构造函数的调用时机
//1.使用已经创建完毕的对象创建新对象
//2.值传递的方式给函数参数传值
//3.值方式返回局部对象
//编译器默认给一个类添加默认构造函数,默认析构函数,默认拷贝构造函数,拷贝属性值
//构造函数调用规则:
// 如果用户定义有参构造函数,编译器不再提供无参,提供拷贝
// 如果定义拷贝,编译器不提供其他
//深拷贝与浅拷贝
// 浅拷贝:简单的赋值拷贝操作
// 深拷贝:在堆区重新申请空间,进行拷贝赋值操作
//初始化列表
//语法:构造函数():属性1(值1),属性2(值2)...{}
//类对象作为类成员,称该成员为对象成员
//构造时先构造类对象,再构造自身
//析构时先析构自身,再析构类对象,与构造顺序相反
//静态成员,分为:静态成员变量、静态成员函数
//静态成员变量特点:
// 所有对象共享同一份数据
// 在编译阶段分配内存(全局区)
// 类内声明,类外初始化
//静态成员函数
// 所有对象共享同一个函数
// 静态成员函数只能访问静态成员变量
//C++对象模型
// 成员变量和成员函数分开存储
// 只有非静态成员变量才属于类的对象上
// 空对象占用1字节
//this指针
// 解决名称冲突
// 返回对象本身用*this(链式编程思想)
//使用this时判断是否为空
//常函数
// 成员函数加const
// 常函数内不能修改成员属性
// 成员属性加mutable关键字可以在常函数中修改
//常对象
// 对象前加const
// 常对象只能调用常函数
//友元
// 有些私有属性,允许类外特殊的一些函数或者类访问
// 关键字 friend
//三种实现:
// 全局函数作友元
// 类作友元
// 成员函数作友元
#include<iostream>
#include"circle.h"
using namespace std;
class Person
{
public:
Person()
{
cout << "Person无参构造函数的调用" << endl;
}
Person(int a)
{
age = a;
cout << "Person有参构造函数的调用" << endl;
}
//拷贝构造
Person(const Person &p)
{
age = p.age;
cout << "Person拷贝构造函数的调用" << endl;
}
~Person()
{
cout << "Person析构函数的调用" << endl;
}
int age;
};
void test01()
{
//1.括号法
Person p1; //默认构造函数
Person p2(10);
Person p3(p2); //拷贝构造函数
//调用默认构造函数时,不要加()
//Person p1(); //不创建对象,编译器认为是函数的声明
//2.显示法
Person p5 = Person(10);
Person p6 = Person(p5);
Person(10); //匿名对象 特点:当前行执行结束后,系统会立即回收掉匿名对象
//不要利用拷贝构造函数初始化匿名对象
//Person(p6); //编译器认为Person(p6);<=>Person p6;
//3.隐式转换法
Person p7 = 10; //相当于Person p7 = Person(10);
Person p8 = p7; //拷贝构造
}
void test02()
{
//使用已经创建完毕的对象创建新对象
Person p1(20);
Person p2(p1);
}
void func01(Person p)
{
return;
}
void test03()
{
Person p;
//值传递的方式给函数参数传值
func01(p);
}
Person func02()
{
//值方式返回局部对象
Person p1;
return p1;
}
void test04()
{
Person p = func02();
}
class Person02 {
public:
Person02()
{
cout << "Person02无参构造" << endl;
}
Person02(int age, int height)
{
cout << "Person02有参构造" << endl;
m_Age = age;
m_Height = new int(height);
}
Person02(const Person02& p)
{
//实现拷贝构造函数,解决浅拷贝带来的问题
cout << "Person02拷贝构造" << endl;
m_Age = p.m_Age;
m_Height = new int(*p.m_Height);
}
~Person02()
{
//析构代码将堆区开辟数据释放
if (m_Height != NULL)
{
delete m_Height;
m_Height = NULL;
}
cout << "Person02析构函数" << endl;
}
int m_Age;
int* m_Height;
};
void test05()
{
Person02 p1(18, 160);
cout << "p1的年龄: " << p1.m_Age << " 身高: " << *p1.m_Height << endl;
Person02 p2(p1);
cout << "p2的年龄: " << p2.m_Age << " 身高: " << *p2.m_Height << endl;
//浅拷贝带来的问题:堆区内存重复释放
}
class Person03
{
public:
//初始化列表
Person03(int a, int b, int c):m_A(a),m_B(b),m_C(c)
{
}
int m_A;
int m_B;
int m_C;
};
class Person04
{
public:
// 所有对象共享同一份数据
// 编译阶段分配内存
// 类内声明,类外初始化
static int m_A;
static void func()
{
cout << "static void func()的调用" << endl;
}
};
int Person04::m_A = 100; //类外初始化
void test06()
{
//静态成员变量的访问
Person04 p;
cout << p.m_A << endl;
cout << Person04::m_A << endl;
p.func();
Person04::func();
}
class Person05
{
public:
//this指针的本质是指针常量(指向的对象不能更改)
void showPerson() const
{
// m_Age = 100;
this->m_B = 100;
}
int m_Age;
mutable int m_B;
};
class Building;
class GoodFriend03
{
public:
GoodFriend03();
void visit();
Building* building;
};
class Building
{
friend void goodFriend01(Building* building);
friend class goodFriend02;
friend void GoodFriend03::visit();
public:
Building()
{
}
public:
string m_Livingroom;
private:
string m_Bedroom = "bedroom";
};
GoodFriend03::GoodFriend03()
{
building = new Building;
}
void GoodFriend03::visit()
{
cout << building->m_Bedroom << endl;
}
void goodFriend01(Building *building)
{
cout << building->m_Bedroom << endl;
}
class goodFriend02
{
public:
goodFriend02()
{
building = new Building;
}
void visit()
{
cout << building->m_Bedroom << endl;
}
Building* building;
};
void test07()
{
// 全局函数作友元
Building building;
goodFriend01(&building);
// 类作友元
goodFriend02 good_f2;
good_f2.visit();
// 类外成员函数作友元
GoodFriend03 good_f3;
}
int main()
{
/*
Circle c1;
c1.setR(10);
cout << c1.calc_circumference() << endl;
*/
// test01();
// test02();
// test04();
// test05();
test07();
system("pause");
return 0;
}
//C++面向对象的三大特性:封装、继承、多态
//三种访问权限
//公共 public 类内可以访问 类外可以访问
//保护 protected 类内可以访问 类外不可以访问
//私有 private 类内可以访问 类外不可以访问
//struct和class区别:
// struct默认权限为公共,class为私有
//成员属性设置成私有:可以控制读写权限,写入时检查合法性
//对象的初始化和清理:
// 构造函数和析构函数
// 构造函数的分类及调用
// 分类:
// 参数:有参和无参
// 类型:普通构造和拷贝构造
// 调用方式:
// 1.括号法
// 2.显示法
// 3.隐式转换法
//拷贝构造函数的调用时机
//1.使用已经创建完毕的对象创建新对象
//2.值传递的方式给函数参数传值
//3.值方式返回局部对象
//编译器默认给一个类添加默认构造函数,默认析构函数,默认拷贝构造函数,拷贝属性值
//构造函数调用规则:
// 如果用户定义有参构造函数,编译器不再提供无参,提供拷贝
// 如果定义拷贝,编译器不提供其他
//深拷贝与浅拷贝
// 浅拷贝:简单的赋值拷贝操作
// 深拷贝:在堆区重新申请空间,进行拷贝赋值操作
//初始化列表
//语法:构造函数():属性1(值1),属性2(值2)...{}
//类对象作为类成员,称该成员为对象成员
//构造时先构造类对象,再构造自身
//析构时先析构自身,再析构类对象,与构造顺序相反
//静态成员,分为:静态成员变量、静态成员函数
//静态成员变量特点:
// 所有对象共享同一份数据
// 在编译阶段分配内存(全局区)
// 类内声明,类外初始化
//静态成员函数
// 所有对象共享同一个函数
// 静态成员函数只能访问静态成员变量
//C++对象模型
// 成员变量和成员函数分开存储
// 只有非静态成员变量才属于类的对象上
// 空对象占用1字节
//this指针
// 解决名称冲突
// 返回对象本身用*this(链式编程思想)
//使用this时判断是否为空
//常函数
// 成员函数加const
// 常函数内不能修改成员属性
// 成员属性加mutable关键字可以在常函数中修改
//常对象
// 对象前加const
// 常对象只能调用常函数
//友元
// 有些私有属性,允许类外特殊的一些函数或者类访问
// 关键字 friend
//三种实现:
// 全局函数作友元
// 类作友元
// 成员函数作友元
#include<iostream>
#include"circle.h"
using namespace std;
class Person
{
public:
Person()
{
cout << "Person无参构造函数的调用" << endl;
}
Person(int a)
{
age = a;
cout << "Person有参构造函数的调用" << endl;
}
//拷贝构造
Person(const Person &p)
{
age = p.age;
cout << "Person拷贝构造函数的调用" << endl;
}
~Person()
{
cout << "Person析构函数的调用" << endl;
}
int age;
};
void test01()
{
//1.括号法
Person p1; //默认构造函数
Person p2(10);
Person p3(p2); //拷贝构造函数
//调用默认构造函数时,不要加()
//Person p1(); //不创建对象,编译器认为是函数的声明
//2.显示法
Person p5 = Person(10);
Person p6 = Person(p5);
Person(10); //匿名对象 特点:当前行执行结束后,系统会立即回收掉匿名对象
//不要利用拷贝构造函数初始化匿名对象
//Person(p6); //编译器认为Person(p6);<=>Person p6;
//3.隐式转换法
Person p7 = 10; //相当于Person p7 = Person(10);
Person p8 = p7; //拷贝构造
}
void test02()
{
//使用已经创建完毕的对象创建新对象
Person p1(20);
Person p2(p1);
}
void func01(Person p)
{
return;
}
void test03()
{
Person p;
//值传递的方式给函数参数传值
func01(p);
}
Person func02()
{
//值方式返回局部对象
Person p1;
return p1;
}
void test04()
{
Person p = func02();
}
class Person02 {
public:
Person02()
{
cout << "Person02无参构造" << endl;
}
Person02(int age, int height)
{
cout << "Person02有参构造" << endl;
m_Age = age;
m_Height = new int(height);
}
Person02(const Person02& p)
{
//实现拷贝构造函数,解决浅拷贝带来的问题
cout << "Person02拷贝构造" << endl;
m_Age = p.m_Age;
m_Height = new int(*p.m_Height);
}
~Person02()
{
//析构代码将堆区开辟数据释放
if (m_Height != NULL)
{
delete m_Height;
m_Height = NULL;
}
cout << "Person02析构函数" << endl;
}
int m_Age;
int* m_Height;
};
void test05()
{
Person02 p1(18, 160);
cout << "p1的年龄: " << p1.m_Age << " 身高: " << *p1.m_Height << endl;
Person02 p2(p1);
cout << "p2的年龄: " << p2.m_Age << " 身高: " << *p2.m_Height << endl;
//浅拷贝带来的问题:堆区内存重复释放
}
class Person03
{
public:
//初始化列表
Person03(int a, int b, int c):m_A(a),m_B(b),m_C(c)
{
}
int m_A;
int m_B;
int m_C;
};
class Person04
{
public:
// 所有对象共享同一份数据
// 编译阶段分配内存
// 类内声明,类外初始化
static int m_A;
static void func()
{
cout << "static void func()的调用" << endl;
}
};
int Person04::m_A = 100; //类外初始化
void test06()
{
//静态成员变量的访问
Person04 p;
cout << p.m_A << endl;
cout << Person04::m_A << endl;
p.func();
Person04::func();
}
class Person05
{
public:
//this指针的本质是指针常量(指向的对象不能更改)
void showPerson() const
{
// m_Age = 100;
this->m_B = 100;
}
int m_Age;
mutable int m_B;
};
class Building;
class GoodFriend03
{
public:
GoodFriend03();
void visit();
Building* building;
};
class Building
{
friend void goodFriend01(Building* building);
friend class goodFriend02;
friend void GoodFriend03::visit();
public:
Building()
{
}
public:
string m_Livingroom;
private:
string m_Bedroom = "bedroom";
};
GoodFriend03::GoodFriend03()
{
building = new Building;
}
void GoodFriend03::visit()
{
cout << building->m_Bedroom << endl;
}
void goodFriend01(Building *building)
{
cout << building->m_Bedroom << endl;
}
class goodFriend02
{
public:
goodFriend02()
{
building = new Building;
}
void visit()
{
cout << building->m_Bedroom << endl;
}
Building* building;
};
void test07()
{
// 全局函数作友元
Building building;
goodFriend01(&building);
// 类作友元
goodFriend02 good_f2;
good_f2.visit();
// 类外成员函数作友元
GoodFriend03 good_f3;
}
int main()
{
/*
Circle c1;
c1.setR(10);
cout << c1.calc_circumference() << endl;
*/
// test01();
// test02();
// test04();
// test05();
test07();
system("pause");
return 0;
}
circle.h
#pragma once
#include <iostream>
using namespace std;
const double PI = 3.14;
class Circle
{
//访问权限
//公共权限
public:
//属性
//行为
void setR(int r);
//获取圆的周长
double calc_circumference();
private:
int m_r;
};
circle.cpp