我有一个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/