in

理解C++中的封装,附带示例

封装是许多编程语言中的一个关键概念。虽然它主要用于面向对象编程(oop)语言,但也是许多其他语言的特性。在使用对象时,我们经常希望将内部工作隐藏在外部类之外。这有助于限制其修改并使其在长期内更加健壮和安全。c++中封装的工作方式与python等其他语言不同。在本文中,我们将详细介绍c++中封装的工作原理以及实现封装的方法。

c++中的封装是什么以及为什么使用它?

封装通常指的是将代码封装成一个单元,从外部类中对内部工作的访问进行限制。您可以将其视为组织内部的机密文件夹,这些文件夹受到保护。只有组织中的某些成员才能访问所有信息,并且通常会根据谁需要访问哪个部分的详细信息进行层次化访问。封装的工作原理与此类似。这导致了更友好的用户界面,数据保护以及更安全的代码。

c++中的封装如何实施?

c++的封装与其他语言有所不同。python没有内置的访问修饰符,而c++具有用于调整代码可见性的访问说明符。这些包括public、private和protected。正如您可能期望的那样,public成员可以从类内部和外部的任何地方访问。但是,private成员只能从同一类内部访问。protected成员可以从类内部访问,也可以从任何派生类访问。

我们还可以在c++中使用友元函数,这些函数可以在类外部访问私有和受保护的成员。这可以提供对代码的灵活使用,但从技术上讲会破坏封装。因此,如果可能的话,通常应避免使用友元函数,并且仅在绝对必要时使用。

c++中封装的示例

有许多情况下封装是可取的。首先,让我们考虑以下示例:

#include <iostream>
using namespace std;

class circle {
private:
    double radius;

public: 
    void setradius(double r) {
        if (r > 0)
            radius = r;
        else
            cout << "invalid radius!" << endl;
    }

    double getradius() {
        return radius;
    }

    double calculatearea() {
        return 3.14 * radius * radius;
    }
};

int main() {
    circle mycircle;
    mycircle.setradius(5.0);
    cout << "radius: " << mycircle.getradius() << endl;
    cout << "area: " << mycircle.calculatearea() << endl;
    
    return 0;
}

在这里,我们定义了私有的”circle”类,其中有私有成员变量”radius”。这只能从类内部访问。该类还有3个公共成员函数 – “setradius”,”getradius”和”calculatearea”。

如果输入的”r”为负数,则”setradius”将报告错误消息。因此,我们控制对此函数的访问,以确保输入无效。因此,”radius”变量被封装起来,其实现对外部类隐藏。

在这个例子中,我们提供了一个半径为5.0的值,该值由”getradius”获取,并由”calculatearea”用于计算圆的面积。输出结果可以在下面的图像中看到。

通过一个例子来说明c++中的封装。

©jingzhengli.com

使用受保护成员的c++封装

前面的例子使用了私有成员来实现封装。然而,也可以使用受保护成员来实现。例如,考虑下面的代码:

#include <iostream>
using namespace std;

class circle {
protected:
    double radius;

public:
    void setradius(double r) {
        if (r > 0)
            radius = r;
        else
            cout << "无效的半径!" < 0)
            height = h;
        else
            cout << "无效的高度!" << endl;
    }

    double getheight() {
        return height;
    }

    double calculatevolume() {
        return calculatearea() * height;
    }
};

int main() {
    cylinder mycylinder;
    mycylinder.setradius(3.0);
    mycylinder.setheight(5.0);

    cout << "半径:" << mycylinder.getradius() << endl;
    cout << "高度:" << mycylinder.getheight() << endl;
    cout << "面积:" << mycylinder.calculatearea() << endl;
    cout << "体积:" << mycylinder.calculatevolume() << endl;

    return 0;
}

这段代码使用了类似的例子,但进行了一些修改。首先,我们有了额外的”cylinder”类,它派生自”circle”。因此,”cylinder”继承了”circle”的函数。由于这个类是protected而不是private,我们可以在派生类中使用这些函数。我们创建了一个名为”mycylinder”的”cylinder”的实例,设置了半径和高度,然后计算了面积和体积。这仍然提供了一定程度的封装,但比私有成员更灵活。

使用受保护成员的封装示例。

©jingzhengli.com

非封装示例

为了展示封装和非封装代码之间的差异,我们可以修改第一个例子,使其不再封装。可以描述如下:

#include <iostream>
using namespace std;

double setradius(double r) {
    if (r > 0)
        return r;
    else {
        cout << "无效的半径!" << endl;
        return 0.0;
    }
}

double getradius(double radius) {
    return radius;
}

double calculatearea(double radius) {
    return 3.14 * radius * radius;
}

int main() {
    double myradius = setradius(5.0);
    double myarea = calculatearea(myradius);

    cout << "半径:" << myradius << endl;
    cout << "面积:" << myarea << endl;

    return 0;
}

我们在这里删除了“circle”类,并用非成员函数替换了成员函数。因此,函数不再访问成员变量,而是将参数作为参数。我们仍然检查半径值的有效性。”setradius”函数将半径值存储在”myradius”中,并将其传递给”calculatearea”以返回圆的面积。总体而言,这意味着可以从类外部直接访问值。如图所示,结果是相同的,但是在c++中封装允许代码更好地组织和重用。

第一个示例程序已经修改为在没有封装的情况下工作。

©jingzhengli.com

总结

封装是所有程序员,特别是使用面向对象编程语言的程序员都需要了解的关键概念。尽管可以使用局部变量实现类似的功能,但封装更可取。这是因为它有助于使代码更加强大,免受外部影响和意外修改的影响,并且通常会导致更简化和有组织的代码。c++使用访问说明符来强制封装,但在适当的情况下可以使用友元函数来减轻这种限制。

Written by 小竞 (编辑)

他们称呼我为小竞, 做作为河小马的助理有5年时间了,作为jingzhengli.com的编辑,我关注每天的科技新闻,帮你归纳一些现有科技以及AI产品来提升你的生产力,拥抱AI,让科技和AI为我们服务!