深入理解C++中的public

在C++中,public是一个访问修饰符(access specifier),用于控制类的成员(包括数据成员和成员函数)以及继承关系的访问权限。当一个类的成员被声明为public时,意味着这些成员可以在类的外部被直接访问。这与privateprotected形成对比,private成员只能在类的内部访问,protected成员可以在类的内部以及该类的派生类中访问。在继承关系中,public关键字用于指定继承的方式,即派生类如何继承基类的成员。

目录

  1. 基础概念
  2. 使用方法
  3. 常见实践
  4. 最佳实践
  5. 小结

基础概念

在C++中,public是一个访问修饰符(access specifier),用于控制类的成员(包括数据成员和成员函数)以及继承关系的访问权限。

当一个类的成员被声明为public时,意味着这些成员可以在类的外部被直接访问。这与privateprotected形成对比,private成员只能在类的内部访问,protected成员可以在类的内部以及该类的派生类中访问。

在继承关系中,public关键字用于指定继承的方式,即派生类如何继承基类的成员。

使用方法

类成员的public声明

下面是一个简单的类定义示例,展示了如何将类成员声明为public

#include <iostream>

class MyClass {
public:
    // 公共数据成员
    int publicData; 

    // 公共成员函数
    void publicFunction() {
        std::cout << "This is a public function." << std::endl;
    }
};

int main() {
    MyClass obj;
    // 直接访问公共数据成员
    obj.publicData = 10; 
    // 调用公共成员函数
    obj.publicFunction(); 

    return 0;
}

在上述代码中,publicDatapublicFunction都被声明为public,因此在main函数中可以直接访问和调用。

继承中的public关键字

当使用public关键字进行继承时,基类的public成员在派生类中仍然是public的,protected成员在派生类中仍然是protected的,而private成员在派生类中是不可访问的。

#include <iostream>

class Base {
public:
    void publicFunction() {
        std::cout << "This is a public function in Base class." << std::endl;
    }
protected:
    int protectedData;
private:
    int privateData;
};

class Derived : public Base {
public:
    void derivedFunction() {
        // 可以访问基类的public成员
        publicFunction(); 
        // 可以访问基类的protected成员
        protectedData = 10; 
        // 不能访问基类的private成员
        // privateData = 20; // 编译错误
    }
};

int main() {
    Derived obj;
    obj.publicFunction(); // 可以从派生类对象访问基类的public函数
    obj.derivedFunction();

    return 0;
}

常见实践

封装数据与提供公共接口

通常,我们会将数据成员声明为private以实现数据封装,然后通过public成员函数提供对这些数据的访问和修改接口。这样可以保证数据的一致性和安全性。

#include <iostream>

class Rectangle {
private:
    int width;
    int height;
public:
    // 构造函数
    Rectangle(int w, int h) : width(w), height(h) {}

    // 获取宽度的公共函数
    int getWidth() const {
        return width;
    }

    // 获取高度的公共函数
    int getHeight() const {
        return height;
    }

    // 设置宽度的公共函数
    void setWidth(int w) {
        if (w >= 0) {
            width = w;
        }
    }

    // 设置高度的公共函数
    void setHeight(int h) {
        if (h >= 0) {
            height = h;
        }
    }

    // 计算面积的公共函数
    int calculateArea() const {
        return width * height;
    }
};

int main() {
    Rectangle rect(5, 3);
    std::cout << "Width: " << rect.getWidth() << std::endl;
    std::cout << "Height: " << rect.getHeight() << std::endl;
    std::cout << "Area: " << rect.calculateArea() << std::endl;

    rect.setWidth(7);
    rect.setHeight(4);
    std::cout << "New Width: " << rect.getWidth() << std::endl;
    std::cout << "New Height: " << rect.getHeight() << std::endl;
    std::cout << "New Area: " << rect.calculateArea() << std::endl;

    return 0;
}

在这个例子中,widthheightprivate数据成员,通过public成员函数getWidthgetHeightsetWidthsetHeight来访问和修改它们,同时通过calculateArea函数提供计算面积的公共接口。

实现公共的成员函数

类的public成员函数通常用于提供类的外部可调用的行为。这些函数可以操作类的内部数据,实现各种功能。

#include <iostream>

class Stack {
private:
    int* data;
    int topIndex;
    int capacity;
public:
    // 构造函数
    Stack(int cap) : capacity(cap), topIndex(-1) {
        data = new int[capacity];
    }

    // 析构函数
    ~Stack() {
        delete[] data;
    }

    // 入栈操作
    void push(int value) {
        if (topIndex < capacity - 1) {
            data[++topIndex] = value;
        }
    }

    // 出栈操作
    int pop() {
        if (topIndex >= 0) {
            return data[topIndex--];
        }
        return -1; // 表示栈为空
    }

    // 判断栈是否为空
    bool isEmpty() const {
        return topIndex == -1;
    }
};

int main() {
    Stack stack(5);
    stack.push(10);
    stack.push(20);
    std::cout << "Popped: " << stack.pop() << std::endl;
    std::cout << "Is empty: " << (stack.isEmpty()? "Yes" : "No") << std::endl;

    return 0;
}

在这个栈的实现中,pushpopisEmpty等函数都是public成员函数,提供了栈的基本操作接口。

最佳实践

最小化public成员的暴露

尽量减少类的public成员的数量,只暴露那些外部必须访问的成员。过多的public成员会破坏数据封装,增加代码的耦合度,使得类的内部实现难以修改。

例如,在一个表示日期的类中,不应该直接暴露年、月、日的成员变量,而是通过合适的public成员函数来提供日期的操作和查询功能。

遵循接口与实现分离原则

将类的public接口设计为清晰、简洁且稳定的抽象,而将具体的实现细节隐藏在private部分。这样,当类的内部实现发生变化时,只要public接口保持不变,外部代码就不需要进行修改。

例如,一个数据库访问类可以提供public的查询、插入、更新和删除等接口函数,而将数据库连接、SQL语句构建等实现细节隐藏在类的内部。

小结

public在C++中是一个重要的访问修饰符,用于控制类成员的访问权限和继承方式。正确使用public关键字可以实现数据封装、提供公共接口以及遵循良好的编程原则。在实际编程中,我们应该谨慎地设计类的public成员,最小化暴露,遵循接口与实现分离原则,以提高代码的可维护性和可扩展性。通过合理运用public,我们能够编写出更加健壮和高效的C++程序。