You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++复合成员对象的getter与setter正确实现方法

作为类成员的自定义对象的Getter/Setter实现

你已经实现了带完整getter/setter的DateOfBirth类,将它的实例作为其他类的私有成员时,getter/setter的实现逻辑和内置类型成员核心一致,只需要根据封装需求选择对应的值/引用/指针返回形式即可,以下是工业界常用的三种实现方案:

前提参考:DateOfBirth类基础实现

class DateOfBirth {
private:
    int month;
    int day;
    int year;
public:
    DateOfBirth(int m = 1, int d = 1, int y = 2000) : month(m), day(d), year(y) {}

    int getMonth() const { return month; }
    void setMonth(int m) { month = m; }
    int getDay() const { return day; }
    void setDay(int d) { day = d; }
    int getYear() const { return year; }
    void setYear(int y) { year = y; }
};

方案1:值语义实现(小型对象首选,最常用)

适合DateOfBirth这种占用空间小、不需要多态的成员对象,核心是避免暴露内部成员的可写权限,同时减少不必要的对象拷贝:

#include <iostream>
class Person {
private:
    DateOfBirth dob; // 私有成员:出生日期对象
public:
    // Getter:返回const引用,无拷贝开销,同时禁止外部修改内部对象
    const DateOfBirth& getDob() const {
        return dob;
    }

    // Setter:接收const引用参数,拷贝赋值给内部成员
    void setDob(const DateOfBirth& newDob) {
        dob = newDob;
    }

    // 重载便利setter:支持直接传入年月日,无需外部提前构造DateOfBirth对象
    void setDob(int m, int d, int y) {
        dob.setMonth(m);
        dob.setDay(d);
        dob.setYear(y);
    }
};

// 调用示例
int main() {
    Person zhangsan;
    // 两种赋值方式
    DateOfBirth tempDob(10, 1, 1999);
    zhangsan.setDob(tempDob);
    zhangsan.setDob(10, 1, 1999);

    // 读取值
    const DateOfBirth& dob = zhangsan.getDob();
    std::cout << dob.getYear() << std::endl; // 正常输出1999
    // dob.setYear(2000);  // 编译报错,const引用无法调用非const的setter
    return 0;
}

方案2:智能指针成员实现(大对象/多态场景适用)

如果成员对象较大、需要运行时多态,通常会用智能指针持有成员,此时setter需要明确所有权转移逻辑,getter禁止暴露可写的指针所有权:

#include <memory>
class Person {
private:
    std::unique_ptr<DateOfBirth> dob;
public:
    // Getter:返回const裸指针,不转移所有权,禁止修改内部对象
    const DateOfBirth* getDob() const {
        return dob.get();
    }

    // Setter:接收unique_ptr参数,通过move转移所有权
    void setDob(std::unique_ptr<DateOfBirth> newDob) {
        dob = std::move(newDob);
    }
};

方案3:代理方法实现(高封装性场景适用)

如果你不希望外部代码拿到完整的DateOfBirth对象,可以直接在容器类中实现代理读写方法,直接操作内部成员的字段,还可以统一加参数合法性校验:

class Person {
private:
    DateOfBirth dob;
public:
    // 代理读方法
    int getBirthMonth() const { return dob.getMonth(); }
    int getBirthDay() const { return dob.getDay(); }
    int getBirthYear() const { return dob.getYear(); }

    // 代理写方法,可统一加业务校验
    void setBirthDate(int m, int d, int y) {
        // 示例校验:月份必须在1-12区间
        if (m < 1 || m > 12) return;
        dob.setMonth(m);
        dob.setDay(d);
        dob.setYear(y);
    }
};

避坑提醒:不要在getter中返回内部成员的非const引用/非const指针,否则外部代码可以绕过类的访问控制直接修改私有成员,彻底破坏类的封装性。如果需要修改内部对象的字段,优先使用整体setter替换对象,或者通过代理setter完成字段修改。

内容的提问来源于stack exchange,提问作者Purmp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 09:48:27