C++类和对象1

简介: C++类和对象

一、封装

1、封装的意义

将属性和行为作为一个整体,表现生活中的事物将属性和行为加以权限控制
#include <iostream>
 
using namespace std;
//圆周率
const double PI = 3.14;
 
//设计圆类,求圆的周长 2*PI*半径
class Circular {
public:
//    半径
    int m_r;
 
// 周长
    double calculateGirth() {
        return 2 * PI * m_r;
    }
};
 
int main() {
//    实例化一个圆
    Circular c1;
    c1.m_r = 10;
    cout << c1.calculateGirth() << endl;
    return 0;
}
 
 
62.8
#include <iostream>
 
using namespace std;
 
//学生
class Student {
public:
    string name;
    int no;
 
    const string &getName() const {
        return name;
    }
 
    void setName(const string &name) {
        Student::name = name;
    }
 
    int getNo() const {
        return no;
    }
 
    void setNo(int no) {
        Student::no = no;
    }
 
    void showInfo() {
        cout << "姓名:"
             << name
             << "学号:"
             << no << endl;
    }
};
 
int main() {
//    实例化
    Student stu;
    stu.name = "zhangsan";
    stu.no = 13131321;
    stu.showInfo();
    return 0;
}
 
 
姓名:zhangsan学号:13131321

三种访问权限

public     成员 类内可以访问 类外可以访问

protected  成员 类内可以访问 类外不可以访问 子类可以访问

private    成员 类内可以访问 类外不可以访问  子类不能访问

#include <iostream>
 
using namespace std;
//三种访问权限
//public     成员 类内可以访问 类外可以访问
//protected  成员 类内可以访问 类外不可以访问 子类可以访问
//private    成员 类内可以访问 类外不可以访问  子类不能访问
 
class Person {
//    共有权限
public:
    string m_Name;//姓名
//保护权限
protected:
    string m_Car;//汽车
//私有权限
private:
//    私有权限
    int m_password;//银行卡密码
public:
    void func() {
        m_Name = "zhangsan";
        m_Car = "xiaopeng";
        m_password = 123456;
    }
 
};
 
int main() {
//实例化具体对象
    Person p1;
    p1.m_Name = "lishi";
 
    return 0;
}
 
 

2、struct和class区别

struct 默认权限为公共
class 默认权限为私有
#include <iostream>
 
using namespace std;
 
class C1 {
    int m_A; //默认私有 private
};
 
struct C2 {
    int m_A; //默认公共 public
};
 
int main() {
//    class与struct区别
    C1 c1;
//    c1.m_A = 12; 无法访问 私有
    C2 c2;
    c2.m_A = 13;
 
    return 0;
}
 
 

3、成员属性设置为私有

优点1:将所有成员属性设置为私有,可以自己控制读写权限;
优点2:对于写权限,我们可以检测数据的有效性。
#include <iostream>
 
using namespace std;
 
class Person {
public:
//    设置姓名
    void setName(string name) {
        m_Name = name;
    }
 
// 获取姓名
    string getName() {
        return m_Name;
    }
 
//设置年龄,检查有效性
    void setAge(int age) {
        if (age > 100 || age < 0) {
            cout << "只能设置0-100之间的数字" << endl;
            return;
        }
        m_Age = age;
    }
 
private:
    string m_Name;
    int m_Age;
};
 
int main() {
    Person p;
    p.setName("zhangsan");
    cout << p.getName() << endl;
    p.setAge(0);
    return 0;
}
 
 

设计立方体类(Cube)

求出立方体的面积和体积

分别用全局函数和成员函数判断两个立方体是否相等。

#include <iostream>
 
using namespace std;
 
class Cube {
public :
//    设置获取长
    void setL(int l) {
        m_L = l;
    }
 
    int getL() {
        return m_L;
    }
 
//    设置获取宽
    void setW(int w) {
        m_W = w;
    }
 
    int getW() {
        return m_W;
    }
 
//    设置获取高
    void setH(int h) {
        m_H = h;
    }
 
    int getH() {
        return m_H;
    }
 
//获取体积
    int calculateS() {
        return 2 * m_L * m_W + 2 * m_W * m_H + 2 * m_H * m_L;
    }
 
//获取面积
    int calculateV() {
        return m_L * m_H * m_W;
    }
 
//成员函数判断
    bool isSameByclass(Cube &c) {
        if (getL() == c.getL() && getH() == c.getH() && getW() == c.getW()) {
            return true;
        }
        return false;
    }
 
private:
    int m_L;//长
    int m_W;//宽
    int m_H;//高
};
 
//全局函数,判断立方体是否相等
bool isSame(Cube &c1, Cube &c2) {
    if (c1.getL() == c2.getL() && c1.getH() == c2.getH() && c1.getW() == c2.getW()) {
        return true;
    }
    return false;
}
 
int main() {
    Cube c1;
    c1.setH(10);
    c1.setW(10);
    c1.setL(10);
    cout << "立方体的面积:" << c1.calculateS() << endl;
    cout << "立方体的体积:" << c1.calculateV() << endl;
 
    Cube c2;
    c2.setH(10);
    c2.setW(10);
    c2.setL(20);
    cout << isSame(c1, c2) << endl;
    cout << c1.isSameByclass(c2) << endl;
    return 0;
}
 
 


立方体的面积:600
立方体的体积:1000
0
0

设计一个圆形类 (Circle) ,和一个点类 (Point) ,计算点和圆的关系。

 #include <iostream>
#include "Point.h"
#include "Circle.h"
 
using namespace std;
 
 
//判断圆和点的关系
void isInCircle(Circle &c, Point &p) {
    int pX = p.getX();
    int pY = p.getY();
    int cX = c.getCenter().getX();
    int cY = c.getCenter().getY();
    int ret = (pX - cX) * (pX - cX) + (pY - cY) * (pY - cY) - c.getR() * c.getR();
    if (ret == 0) {
        cout << "点在圆上" << endl;
 
    } else if (ret < 0) {
        cout << "点在圆内" << endl;
    } else {
        cout << "点在圆外" << endl;
    }
}
 
int main() {
    Point p;
    p.setX(0);
    p.setY(0);
    Circle c;
    c.setCenter(p);
    c.setR(10);
    Point p1;
    p1.setX(10);
    p1.setY(0);
    Point p2;
    p2.setX(-11);
    p2.setY(0);
    isInCircle(c, p);
    isInCircle(c, p1);
    isInCircle(c, p2);
    return 0;
}
 
 

Point.h

#pragma once //防止头文件重复包含
 
#include <iostream>
 
using namespace std;
 
//点类
class Point {
public :
    void setX(int x);
 
    int getX();
 
    void setY(int y);
 
    int getY();
 
private:
    int m_X;
    int m_Y;
};
 

Point.cpp

#include "Point.h"
 
void Point::setX(int x) {
    m_X = x;
}
 
int Point::getX() {
    return m_X;
}
 
void Point::setY(int y) {
    m_Y = y;
}
 
int Point::getY() {
    return m_Y;
}

Circle.h

#pragma once //防止头文件重复包含
 
#include <iostream>
#include "Point.h"
 
using namespace std;
 
//圆类
class Circle {
public:
    void setR(int r);
 
    int getR();
 
    void setCenter(Point point);
 
    Point getCenter();
 
 
private:
    int m_R;//半径
    Point m_Center;//圆心
};

Circle.cpp

#include "Circle.h"
 
//圆类
void Circle::setR(int r) {
    m_R = r;
}
 
int Circle::getR() {
    return m_R;
}
 
void Circle::setCenter(Point point) {
    m_Center = point;
}
 
Point Circle::getCenter() {
    return m_Center;
}

程序运行结果

点在圆内
点在圆上
点在圆外


二、对象的初始化和清理

1、构造函数和析构函数

#include <iostream>
 
using namespace std;
 
//对象的初始化和清理
//1、构造函数 进行初始化操作
class Person {
public:
    /**
     * 构造函数没有返回值,不用写void
     * 函数名与类名相同
     * 构造函数可以后参数,可以发生重载
     * 创建对象的时候,构造函数会自动调用,而且只调用一次
     */
    Person() {
        cout << "Person 无参构造函数调用了" << endl;
    }
//2、析构函数进行清理的操作
/**
 * 没有返回值 不写void
 * 函数名与类名相同 在名称前加~
 * 析构函数不可以有参数,不可以发生重载
 * 对象在销毁前,会自动调用析构函数,只调用一次
 */
    ~Person() {
        cout << "Person 析构函数调用了" << endl;
    }
};
 
 
int main() {
    Person p1;
    return 0;
}
 
 


Person 无参构造函数调用了
Person 析构函数调用了

2、构造函数的分类和调用

#include <iostream>
 
using namespace std;
 
//对象的初始化和清理
class Person {
public:
 
//   构造函数 按照参数分类 有参和无参
    Person() {
        cout << "Person 无参构造函数调用了" << endl;
    }
 
    Person(int a) {
        age = a;
        cout << "Person 有参构造函数调用了" << endl;
    }
 
//按照类型分类 普遍构造函数和拷贝构造函数
//拷贝构造函数
    Person(const Person &person) {
        cout << "Person 拷贝构造函数调用了" << endl;
        age = person.age;
    }
 
    //析构函数
    ~Person() {
        cout << "Person 析构函数调用了" << endl;
    }
 
public:
    int age;
};
 
//调用
void test() {
//    1、括号法
    Person p1; //默认、无参,调用默认参数不使用();  Person p1();会被认为是函数p1的申明;
    Person p2(10);//有参
    Person p3(p2);//拷贝
    cout << p2.age << endl;
    cout << p3.age << endl;
//2、显示法
    Person p21;
    Person p22 = Person(10); //有参构造
    Person p23 = Person(p22); //拷贝构造
 
//Person(10);匿名对象,当前行执行后,系统会立即回收掉匿名对象;
//Person(p3); 不用利用拷贝对象初始化匿名对象 编译器会认为Person(p3)===Person p3;
 
//3、隐式转换法
    Person p4 = 20;//Person p4=Person(20);
    Person p5 = p4;//Person p5=Person(p4);
}
 
int main() {
    test();
    return 0;
}
 
 
Person 无参构造函数调用了
Person 有参构造函数调用了
Person 拷贝构造函数调用了
10
10
Person 无参构造函数调用了
Person 有参构造函数调用了
Person 拷贝构造函数调用了
Person 有参构造函数调用了
Person 拷贝构造函数调用了
Person 析构函数调用了
Person 析构函数调用了
Person 析构函数调用了
Person 析构函数调用了
Person 析构函数调用了
Person 析构函数调用了
Person 析构函数调用了
Person 析构函数调用了

3、拷贝构造函数调用时机

使用一个已经创建完毕的对象来初始化一个新对象
值传递的方式给函数参数传值
以值的方式返回局部对象
#include <iostream>
 
using namespace std;
//拷贝构造函数调用时机
 
class Person {
public:
    Person() {
        cout << "Person默认构造函数调用" << endl;
    }
 
    Person(int a) {
        m_Age = a;
        cout << "Person有参构造函数" << endl;
    }
 
    Person(const Person &p) {
        m_Age = p.m_Age;
        cout << "Person拷贝构造函数" << endl;
    }
 
    ~Person() {
        cout << "Person析构函数调用" << endl;
    }
 
    int m_Age;
};
 
//1、使用一个已经创建完毕的对象来初始化一个新对象(最常用)
void test01() {
    Person p1(10);
    Person p2(p1);
}
 
//2、值传递的方式给函数参数传值
void doWork(Person p) {
 
}
 
//值传递,会拷贝一个临时副本
void test02() {
    Person p;
    doWork(p);
}
 
//3、值方式返回局部对象
Person doWork2() {
    Person p1;
    cout << &p1 << endl;
    return p1;
}
 
void test03() {
    Person p = doWork2();
    cout << &p << endl;
}
 
int main() {
//    test01();
//    test02();
    test03();
    return 0;
 
 
}
 
 
Person默认构造函数调用
0x66fd0c
0x66fd0c
Person析构函数调用

C++类和对象2:https://developer.aliyun.com/article/1548157

目录
相关文章
|
1天前
|
C++
【C++】日期类Date(详解)②
- `-=`通过复用`+=`实现,`Date operator-(int day)`则通过创建副本并调用`-=`。 - 前置`++`和后置`++`同样使用重载,类似地,前置`--`和后置`--`也复用了`+=`和`-=1`。 - 比较运算符重载如`&gt;`, `==`, `&lt;`, `&lt;=`, `!=`,通常只需实现两个,其他可通过复合逻辑得出。 - `Date`减`Date`返回天数,通过迭代较小日期直到与较大日期相等,记录步数和符号。 ``` 这是236个字符的摘要,符合240字符以内的要求,涵盖了日期类中运算符重载的主要实现。
|
1天前
|
存储 编译器 C++
【C++】类和对象④(再谈构造函数:初始化列表,隐式类型转换,缺省值
C++中的隐式类型转换在变量赋值和函数调用中常见,如`double`转`int`。取引用时,须用`const`以防修改临时变量,如`const int& b = a;`。类可以有隐式单参构造,使`A aa2 = 1;`合法,但`explicit`关键字可阻止这种转换。C++11起,成员变量可设默认值,如`int _b1 = 1;`。博客探讨构造函数、初始化列表及编译器优化,关注更多C++特性。
|
1天前
|
编译器 C++
【C++】类和对象④(类的默认成员函数:取地址及const取地址重载 )
本文探讨了C++中类的成员函数,特别是取地址及const取地址操作符重载,通常无需重载,但展示了如何自定义以适应特定需求。接着讨论了构造函数的重要性,尤其是使用初始化列表来高效地初始化类的成员,包括对象成员、引用和const成员。初始化列表确保在对象创建时正确赋值,并遵循特定的执行顺序。
|
1天前
|
C语言 C++
【C++】日期类Date(详解)③
该文介绍了C++中直接相减法计算两个日期之间差值的方法,包括确定max和min、按年计算天数、日期矫正及计算差值。同时,文章讲解了const成员函数,用于不修改类成员的函数,并给出了`GetMonthDay`和`CheckDate`的const版本。此外,讨论了流插入和流提取的重载,需在类外部定义以符合内置类型输入输出习惯,并介绍了友元机制,允许非成员函数访问类的私有成员。全文旨在深化对运算符重载、const成员和流操作的理解。
|
1天前
|
定位技术 C语言 C++
C++】日期类Date(详解)①
这篇教程讲解了如何使用C++实现一个日期类`Date`,涵盖操作符重载、拷贝构造、赋值运算符及友元函数。类包含年、月、日私有成员,提供合法性检查、获取某月天数、日期加减运算、比较运算符等功能。示例代码包括`GetMonthDay`、`CheckDate`、构造函数、拷贝构造函数、赋值运算符和相关运算符重载的实现。
|
1天前
|
编译器 C++
【C++】类和对象③(类的默认成员函数:赋值运算符重载)
在C++中,运算符重载允许为用户定义的类型扩展运算符功能,但不能创建新运算符如`operator@`。重载的运算符必须至少有一个类类型参数,且不能改变内置类型运算符的含义。`.*::sizeof?`不可重载。赋值运算符`=`通常作为成员函数重载,确保封装性,如`Date`类的`operator==`。赋值运算符应返回引用并检查自我赋值。当未显式重载时,编译器提供默认实现,但这可能不足以处理资源管理。拷贝构造和赋值运算符在对象复制中有不同用途,需根据类需求定制实现。正确实现它们对避免数据错误和内存问题至关重要。接下来将探讨更多操作符重载和默认成员函数。
|
1天前
|
存储 编译器 C++
【C++】类和对象③(类的默认成员函数:拷贝构造函数)
本文探讨了C++中拷贝构造函数和赋值运算符重载的重要性。拷贝构造函数用于创建与已有对象相同的新对象,尤其在类涉及资源管理时需谨慎处理,以防止浅拷贝导致的问题。默认拷贝构造函数进行字节级复制,可能导致资源重复释放。例子展示了未正确实现拷贝构造函数时可能导致的无限递归。此外,文章提到了拷贝构造函数的常见应用场景,如函数参数、返回值和对象初始化,并指出类对象在赋值或作为函数参数时会隐式调用拷贝构造。
|
1天前
|
存储 编译器 C语言
【C++】类和对象②(类的默认成员函数:构造函数 | 析构函数)
C++类的六大默认成员函数包括构造函数、析构函数、拷贝构造、赋值运算符、取地址重载及const取址。构造函数用于对象初始化,无返回值,名称与类名相同,可重载。若未定义,编译器提供默认无参构造。析构函数负责对象销毁,名字前加`~`,无参数无返回,自动调用以释放资源。一个类只有一个析构函数。两者确保对象生命周期中正确初始化和清理。
|
4天前
|
存储 编译器 C语言
【C++航海王:追寻罗杰的编程之路】类与对象你学会了吗?(上)
【C++航海王:追寻罗杰的编程之路】类与对象你学会了吗?(上)
9 2
|
3天前
|
C++
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
7 0
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)