c++ - 通过扩展添加可变性

标签 c++ inheritance constants

我有一个Data 类和一个Wrapper 类,它提供了访问Data 的方法。 WrapperMutable 类扩展了 Wrapper 以添加修改 Data 的方法。

#include <memory>
using namespace std;

class Data {
public:
    void update();  // non-const method which modifies internal state of Data
};

class Wrapper
{
public:
  Wrapper(shared_ptr<Data const> data) : myData(data) {}  // accepts const pointer
  // ...bunch of functions providing read-only access to aspects of the Data...
protected:
  shared_ptr<Data const> myData;  // stores const pointer
};

// Extend Wrapper with methods to modify the wrapped Data.
class WrapperMutable : public Wrapper
{
public:
  WrapperMutable(shared_ptr<Data> data) : Wrapper(data) {}

  // ERROR: invoking non-const method on const object:
  void updateData() { myData->update(); } 
};

问题当然出在被包装的Data 对象的const 特性上,这意味着WrapperMutable 不能修改它。

我考虑过更改 Wrapper 以接受和存储非 const Data,但客户端本身通常只能访问 const Data,因此他们将被迫 const_cast 或复制以创建 Wrapper

所以我能够实现这一点的唯一方法是在 WrapperMutable 类中保留一个额外的非 const 指针,并在可变上下文中使用它:

class WrapperMutable : public Wrapper
{
public:
  WrapperMutable(shared_ptr<Data> data) : Wrapper(data), myMutableData(data) {}

  // Use myMutableData instead of the const myData
  void updateData() { myMutableData->update(); }

private:
  shared_ptr<Data> myMutableData;  // non-const pointer to the same Data as in Wrapper
};

有没有更好的方法?显然,从 Wrapper 派生 WrapperMutable 是我问题的根源,但我不想在中重新实现 Wrapper 的所有方法WrapperMutable 要么。

最佳答案

继承表示一种“种类”关系。

常量不是一种“种类”关系。

常量事物与可变事物截然不同。

shared_ptr 的模型本身就展示了如何表达这种关系。可变数据的 shared_ptr 可转换为常量数据的 shared_ptr,但反之则不行。

你可以这样表达这种关系:

#include <iostream>
#include <memory>

struct Data
{
};

struct const_data_wrapper
{
    const_data_wrapper(std::shared_ptr<const Data> p) : _impl(std::move(p)) {}

    void which() const {
        std::cout << "const" << std::endl;
    }

private:
    std::shared_ptr<const Data> _impl;
};

struct data_wrapper
{
    data_wrapper(std::shared_ptr<Data> p) : _impl(std::move(p)) {}

    const_data_wrapper as_const() const {
        return const_data_wrapper(_impl);
    }

    void which() const {
        std::cout << "not const" << std::endl;
    }

private:
    std::shared_ptr<Data> _impl;
};

using namespace std;

auto main() -> int
{
    auto w1 = data_wrapper(make_shared<Data>());
    auto w2 = w1.as_const();

    w1.which();
    w2.which();

    return 0;
}

输出:

not const
const

关于c++ - 通过扩展添加可变性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33629801/

相关文章:

python - 我应该在 Python 中实现具有常量接口(interface)的类吗?

c++ - 同一地址的变量如何产生 2 个不同的值?

java - 具有泛型方法的泛型类的协变

c++ - 在 .so 库中使用 C++ 类

c++ - 如何在Visual Studio中设置让C++/C代码只在一个线程中运行来测试运行时间?

c++ - C++字符串流

JavaScript:解释继承、__proto__ 和原型(prototype)的图表

iphone - 在 Xcode 中如何抑制 "incomplete implementation"?(继承)

C 和 execve(3) 参数

c++ - 显式 operator= call (T::operator=)