13x1类和对象-1-封装

关注泷羽Sec-静安 公众号,后台回复 找书+ C++Primer 获取C++相关电子书

image-20250211221401317

  • 类:类是一个抽象的模板,用于定义对象的属性和行为。
  • 对象:对象是类的具体实例,通过类创建。

面向对象三大特性:

  • 封装 (Encapsulation):通过将数据成员设为私有(private),并提供公共(public)方法来控制对数据的访问,保护数据不被外部直接修改。
  • 继承 (Inheritance):通过继承基类的属性和方法,派生类可以复用基类的代码,并可以添加新的属性和方法。
  • 多态 (Polymorphism):通过基类指针或引用调用派生类的重写方法,实现同一接口的不同实现。
#include <iostream>
#include <string>

using namespace std;

/*----------- 类和对象基础 -----------*/
// 类:抽象模板 | 对象:具体实例
class Dog {          // 类声明
public:
    string name;     // 属性
    void bark() {    // 方法
        cout << name << ": Wang Wang!" << endl;
    }
};

// 使用示例:
int main() {
    Dog myDog;           // 创建对象
    myDog.name = "Buddy";
    myDog.bark();        // 输出:Buddy: Wang Wang!

    /*----------- 封装 (Encapsulation) -----------*/
    class BankAccount {
    private:             // 封装敏感数据
        double balance;

    public:
        // 公开接口控制访问
        void deposit(double amount) {
            if (amount > 0) balance += amount;
        }

        bool withdraw(double amount) {
            if (amount <= balance) {
                balance -= amount;
                return true;
            }
            return false;
        }

        double getBalance() { return balance; } // 只读访问
    };

    // 使用示例:
    BankAccount acc;
    acc.deposit(1000);      // 合法操作
    // acc.balance = 10000; // 错误:无法直接访问private成员

    /*----------- 继承 (Inheritance) -----------*/
    // 基类
    class Vehicle {
    public:
        string brand;
        void honk() {
            cout << "Tu~ Tu~" << endl;
        }
    };

    // 派生类
    class Car : public Vehicle { // 继承语法
    public:
        int wheels = 4;         // 新增属性
        void showSpec() {       // 新增方法
            cout << brand << " Car with " << wheels << " wheels" << endl;
        }
    };

    // 使用示例:
    Car myCar;
    myCar.brand = "BMW";  // 继承自基类
    myCar.honk();         // 调用基类方法
    myCar.showSpec();     // 输出:BMW Car with 4 wheels

    /*----------- 多态 (Polymorphism) -----------*/
    class Shape {  //一个形状
    public:
        virtual double area() { // 虚函数实现多态基础
            return 0;
        }
    };

    class Circle : public Shape { //圆
        double radius;
    public:
        Circle(double r) : radius(r) {}
        double area() override { // 重写基类方法
            return 3.14159 * radius * radius;
        }
    };

    class Rectangle : public Shape {  //角度
        double width, height;
    public:
        Rectangle(double w, double h) : width(w), height(h) {}
        double area() override { // 重写基类方法
            return width * height;
        }
    };

    // 使用示例:
    Shape* shapes[2];          // 基类指针数组
    shapes[0] = new Circle(5); // 指向派生类对象
    shapes[1] = new Rectangle(4, 6);

    // 同一接口表现不同行为
    cout << "Circle area: " << shapes[0]->area() << endl;  // 输出78.5397
    cout << "Rectangle area: " << shapes[1]->area() << endl; // 输出24

    /* 多态实现关键点:
    1. 基类方法声明为virtual
    2. 派生类使用override重写方法
    3. 通过基类指针/引用调用方法 */

    // 清理动态分配的内存
    delete shapes[0];
    delete shapes[1];

    return 0;
}
---
Buddy: Wang Wang!
Tu~ Tu~
BMW Car with 4 wheels
Circle area: 78.5397
Rectangle area: 24

三种访问权限

  • 公共权限(public):公共成员可以在任何地方访问,包括类外部和派生类中。
    示例:int publicVar; 可以在 main 函数中直接访问。
  • 保护权限(protected):保护成员只能在本类和派生类中访问,不能在类外部访问。
    示例:int protectedVar; 可以在派生类 Derived 中访问,但不能在 main 函数中直接访问。
  • 私有权限(private):私有成员只能在本类中访问,不能在类外部和派生类中访问。
    示例:int privateVar; 只能在 Base 类的成员函数中访问,不能在 main 函数和派生类 Derived 中直接访问。
#include <iostream>
#include <string>

using namespace std;

/*----------- 访问权限示例 -----------*/
class Base {
public:
    int publicVar; // 公共权限:任何地方都可以访问

protected:
    int protectedVar; // 保护权限:派生类和本类可以访问

private:
    int privateVar; // 私有权限:只有本类可以访问

public:
    // 构造函数
    Base(int pub, int prot, int priv) : publicVar(pub), protectedVar(prot), privateVar(priv) {}

    // 公共方法,访问私有成员
    void showPrivateVar() {
        cout << "Private Variable: " << privateVar << endl;
    }
};

// 派生类
class Derived : public Base {
public:
    // 构造函数
    Derived(int pub, int prot, int priv) : Base(pub, prot, priv) {}

    // 访问基类的保护成员
    void showProtectedVar() {
        cout << "Protected Variable: " << protectedVar << endl;
    }
};

int main() {
    // 创建基类对象
    Base baseObj(1, 2, 3);

    // 访问公共成员
    cout << "Public Variable: " << baseObj.publicVar << endl;

    // 访问私有成员(错误)
    // cout << "Private Variable: " << baseObj.privateVar << endl; // 错误:无法访问私有成员

    // 通过公共方法访问私有成员
    baseObj.showPrivateVar();

    // 创建派生类对象
    Derived derivedObj(4, 5, 6);

    // 访问基类的公共成员
    cout << "Public Variable (Derived): " << derivedObj.publicVar << endl;

    // 访问基类的保护成员(错误)
    // cout << "Protected Variable (Derived): " << derivedObj.protectedVar << endl; // 错误:无法直接访问保护成员

    // 通过派生类方法访问基类的保护成员
    derivedObj.showProtectedVar();

    return 0;
}
---
Public Variable: 1
Private Variable: 3
Public Variable (Derived): 4
Protected Variable: 5

struct 和 class的区别

在C++中,struct 和 class 的主要区别在于默认的访问控制权限。以下是详细的解释和示例代码:
区别

  1. 默认访问控制权限:
    struct 的成员默认是 public。
    class 的成员默认是 private。
  2. 继承:
    struct 默认的继承方式是 public。
    class 默认的继承方式是 private。
#include <iostream>
#include <string>

using namespace std;

// 使用 struct
struct MyStruct {
    int publicVar; // 默认是 public

    MyStruct(int val) : publicVar(val) {}
};

// 使用 class
class MyClass {
    int privateVar; // 默认是 private

public:
    MyClass(int val) : privateVar(val) {}

    int getPrivateVar() const {
        return privateVar;
    }
};

int main() {
    // 使用 struct
    MyStruct s(10);
    cout << "MyStruct publicVar: " << s.publicVar << endl; // 可以直接访问

    // 使用 class
    MyClass c(20);
    // cout << "MyClass privateVar: " << c.privateVar << endl; // 错误:无法直接访问 private 成员
    cout << "MyClass privateVar: " << c.getPrivateVar() << endl; // 通过公共方法访问

    return 0;
}

---
MyStruct publicVar: 10
MyClass privateVar: 20

成员属性设置为私有

优点

  1. 封装性:将成员对象设置为私有可以隐藏对象的内部实现细节,只暴露必要的接口,增强了代码的封装性。
  2. 数据完整性:通过私有成员和公有方法,可以控制对数据的访问和修改,防止外部代码直接修改对象的状态,保证数据的完整性和一致性。
  3. 易于维护:由于内部实现细节被隐藏,修改内部实现不会影响外部代码,增强了代码的可维护性。
  4. 安全性:私有成员只能通过类的公有方法访问,减少了数据被意外或恶意修改的风险。

风险

  1. 性能开销:访问私有成员需要通过公有方法,这可能会带来一些性能开销,尤其是在频繁访问的情况下。
  2. 代码复杂性:为了访问和修改私有成员,需要编写额外的公有方法,可能会增加代码的复杂性。
  3. 灵活性降低:私有成员的访问受到限制,可能会降低代码的灵活性,某些情况下需要使用友元类或友元函数来访问私有成员。
#include <iostream>
#include <string>

using namespace std;

class PersonConnect { //通讯录类
private: //私有属性
    string PName; //姓名
    int PSex = 0; //性别 1 男 2 女
    int PAge = 0; //年龄
    string PPhone; //电话
    string PAddress; //住址

public: //公有函数方法
    // 设置姓名
    void setName(const string& name) {
        PName = name;
    }

    // 获取姓名
    string getName() const {
        return PName;
    }

    // 设置性别
    void setSex(int sex) {
        if (sex == 1 || sex == 2) {
            PSex = sex;
        }
        else {
            cout << "性别输入有误" << endl;
        }
    }

    // 获取性别
    int getSex() const {
        return PSex;
    }

    // 设置年龄
    void setAge(int age) {
        PAge = age;
    }

    // 获取年龄
    int getAge() const {
        return PAge;
    }

    // 设置电话
    void setPhone(const string& phone) {
        PPhone = phone;
    }

    // 获取电话
    string getPhone() const {
        return PPhone;
    }

    // 设置地址
    void setAddress(const string& address) {
        PAddress = address;
    }

    // 获取地址
    string getAddress() const {
        return PAddress;
    }
};

int main() {
    PersonConnect person;
    person.setName("张三");
    person.setSex(1);
    person.setAge(30);
    person.setPhone("123456789");
    person.setAddress("北京市");

    cout << "姓名:" << person.getName() << endl;
    cout << "性别:" << (person.getSex() == 1 ? "男" : "女") << endl;
    cout << "年龄:" << person.getAge() << endl;
    cout << "电话:" << person.getPhone() << endl;
    cout << "地址:" << person.getAddress() << endl;

    return 0;
}
---
姓名:张三
性别:男
年龄:30
电话:123456789
地址:北京市

练习案例1-设计立方体类

设计立方体类,求立方体面积和体积,分别用全局函数和成员函数判断两个立方体是否相等。

#include<iostream>
using namespace std;

/*
* 立方体类设计
* 1. 设计立方体类,求立方体的面积和体积
* 2. 分别用全局函数和成员函数判断两个立方体是否相等
*/

class Cube
{
private: // 私有权限
	int	m_L; // 长
	int m_W; // 宽
	int m_H; // 高

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 + m_W * m_H + m_L * m_H);
	}
	// 获取立方体的体积
	int calculateV()
	{
		return m_L * m_W * m_H;
	}
	// 判断两个立方体是否相等(成员函数)
	bool isSameByClass(Cube& c)
	{
		if (m_L == c.getL() && m_W == c.getW() && m_H == c.getH())
		{
			return true;
		}
		return false;
	}

};

// 判断两个立方体是否相等(全局函数)
bool isSame(Cube& c1, Cube& c2)
{
	if (c1.getL() == c2.getL() && c1.getW() == c2.getW() && c1.getH() == c2.getH())
	{
		return true;
	}
	return false;
}
int main()
{
	Cube c1;
	c1.setL(10);
	c1.setW(10);
	c1.setH(10);

	cout << "c1的面积为:" << c1.calculateS() << endl;
	cout << "c1的体积为:" << c1.calculateV() << endl;

	Cube c2;
	c2.setL(10);
	c2.setW(10);
	c2.setH(10);

	cout << "c2的面积为:" << c2.calculateS() << endl;
	cout << "c2的体积为:" << c2.calculateV() << endl;

	Cube c3;
	c3.setL(20);
	c3.setW(20);
	c3.setH(20);

	cout << "c3的面积为:" << c3.calculateS() << endl;
	cout << "c3的体积为:" << c3.calculateV() << endl;


	bool ret = c1.isSameByClass(c2); // 判断两个立方体是否相等(成员函数)
	if (ret)
	{
		cout << "c1和c2相等" << endl;
	}
	else
	{
		cout << "c1和c2不相等" << endl;
	}

	bool ret2 = isSame(c1, c3); // 判断两个立方体是否相等(全局函数)
	if (ret2)
	{
		cout << "c1和c3相等" << endl;
	}
	else
	{
		cout << "c1和c3不相等" << endl;
	}
	return 0;
}
/*
c1的面积为:600
c1的体积为:1000
c2的面积为:600
c2的体积为:1000
c3的面积为:2400
c3的体积为:8000
c1和c2相等
c1和c3不相等
*/

练习案例2-点和圆的关系

点在圈内,点在圆圈上,点在圆圈外。思路:设置圆类,圆心和半径;设置点,点坐标,求两点之间距离。

#include<iostream>
using namespace std;
/*
* 点在圈内,点在圆圈上,点在圆圈外。思路:设置圆类,圆心和半径;设置点,点坐标,求两点之间距离。
*/

class Point
{
public:
	//设置点坐标
	void setPoint(int x, int y)
	{
		Px = x;
		Py = y;
	}

	//获取点坐标
	int getPointX()
	{
		return Px;
	}
	int getPointY()
	{
		return Py;
	}

private:
	int Px; //点坐标
	int Py;

};

class Clcle
{
public:
	//设置圆心和半径
	void setClcle(int x, int y, int r)
	{
		Cx = x;
		Cy = y;
		Cr = r;
	}

	//判断点在圆内,圆上,圆外
	int judge(Point p)
	{
		int dis = (p.getPointX() - Cx) * (p.getPointX() - Cx) + (p.getPointY() - Cy) * (p.getPointY() - Cy);
		if (dis < Cr * Cr)
		{
			return 1; //点在圆内
		}
		else if (dis == Cr * Cr)
		{
			return 0; //点在圆上
		}
		else
		{
			return -1; //点在圆外
		}
	}
private:
	int Cx; //圆心坐标
	int Cy;
	int Cr; //半径

};


int main()
{
	Point p;
	p.setPoint(1, 1);

	Clcle c;
	c.setClcle(0, 0, 2);

	int result = c.judge(p);

	if (result == 1)
	{
		cout << "点在圆内" << endl;
	}
	else if (result == 0)
	{
		cout << "点在圆上" << endl;
	}
	else
	{
		cout << "点在圆外" << endl;
	}
	
	return 0;
}
___
点在圆内

🔔 想要获取更多网络安全与编程技术干货?

关注 泷羽Sec-静安 公众号,与你一起探索前沿技术,分享实用的学习资源与工具。我们专注于深入分析,拒绝浮躁,只做最实用的技术分享!💻

扫描下方二维码,马上加入我们,共同成长!🌟

👉 长按或扫描二维码关注公众号

或者直接回复文章中的关键词,获取更多技术资料与书单推荐!📚

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泷羽Sec-静安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值