Skip to content

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;
}

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

#include "circle.h"

void Circle::setR(int r)
{
    m_r = r;
}
//获取圆的周长
double Circle::calc_circumference()
{
    return 2 * PI * m_r;
}