首页 > 解决方案 > 如何利用对私有(结构)成员的公共常量引用进行代码封装

问题描述

在我的错误类中,我只公开了 的常量版本MyStruct,尝试在初始化列表中初始化对私有成员的常量引用。

我正在调试的程序在功能上等同于以下内容:

#include <iostream>
#include <optional>

struct MyStruct {
  int member = 1;
};

class MyType {
  MyStruct struct_member_;
public:
  MyType() : struct_member(struct_member_) {}
  MyType& operator =(const MyType& other_side) {
    struct_member_ = other_side.struct_member_;
    return *this;
  };
  const MyStruct& struct_member;
  void test() const {
    std::cout << "Why isn't " << &struct_member << " the same as " << &struct_member_ << std::endl;
  }
};

int main()
{
    std::optional<MyType> my = MyType();
    my.value().test();

    std::optional<MyType> yours = MyType();
    yours.value().test();

    my = yours;
    my.value().test();

    my = MyType();
    my.value().test();

    return 0;
}

对于这个程序,输出如下:

Why isn't 0x7ffeefbff890 the same as 0x7ffeefbff8a0
Why isn't 0x7ffeefbff868 the same as 0x7ffeefbff878
Why isn't 0x7ffeefbff890 the same as 0x7ffeefbff8a0
Why isn't 0x7ffeefbff890 the same as 0x7ffeefbff8a0

但是,在我正在调试的程序中,struct_member_并且struct_member正在去同步(常量引用struct_member被分配到内存中的不同位置——除了它是常量,或者它在更新后失去了轨道struct_member_——除了它的内存地址不应该改变?)我不确定是哪个或为什么。

关于什么可能导致这种情况发生的任何想法,或者使这种模式适用于非 POD 类型的提示?(无论如何,我计划过渡到基于方法的访问器,因为这个实验似乎失败了。)

标签: c++

解决方案


事实证明,可选项和复制构造函数是所有这些的关键。复制构造函数是默认的,我没有意识到。有趣,因为编译器警告我需要一个非默认值operator=,但没有为复制构造函数提供相同的警告。

class MyType {
  MyStruct struct_member_;
public:
  MyType() : struct_member(struct_member_) {
    std::cout << "constructor" << std::endl;
  }
  MyType(const MyType& other) : struct_member(struct_member_) {
    std::cout << "copy constructor " << std::endl;
    struct_member_ = other.struct_member_;
  };
  MyType& operator =(const MyType& other_side) {
    std::cout << "assignment operator called" << std::endl;
    struct_member_ = other_side.struct_member_;
    return *this;
  };
  const MyStruct& struct_member;
  void test() const {
    std::cout << "Why isn't " << struct_member.member << ": " << &struct_member << " the same as " << &struct_member_ << std::endl;
  }
};

产生正确的输出:

constructor
copy constructor 
Why isn't 0x7ffeefbff8a0 the same as 0x7ffeefbff8a0
constructor
copy constructor 
Why isn't 0x7ffeefbff878 the same as 0x7ffeefbff878
assignment operator called
Why isn't 0x7ffeefbff8a0 the same as 0x7ffeefbff8a0
constructor
assignment operator called
Why isn't 0x7ffeefbff8a0 the same as 0x7ffeefbff8a0

总而言之,仅仅将 getter 公开为方法就不会那么麻烦了。


推荐阅读