c++ - Const 和非常量访问解析为不同的重载?

标签 c++ design-patterns templates

假设我们有一个简单的编程任务。但为了清楚起见,我从几个代码示例开始。 首先,我们编写了某种数据容器类,但不管类是什么,都是为了任务的目的。我们只需要它表现出 const-correct 的行为。

class DataComponent {
public:
    const std::string& getCaption() const {
        return caption;
    }

    void setCaption(const std::string& s) {
        caption = s;
    }

private:
    std::string caption;
};

然后让我们假设我们有一个通用类,其行为类似于任意封装类实例的外观。假设我们重载了成员访问运算符 ( -> )。

template <typename T> class Component {
public:
    Component() { instance = new T(); }

    ...

    const T* operator-> () const {
        return instance;
    }

    T* operator-> () {
        // but there might be additional magic
        return instance;
    }

private:
    T *instance;
};

此时我应该说出我希望它如何工作:

  • 如果我们通过成员访问运算符 ( component->setCaption("foo") ) 调用底层类的非常量成员函数,编译器会处理非常量 T* operator-> ()作为最佳选择。
  • 否则,如果我们尝试以相同方式调用底层类的 const 成员函数 (component->getCaption()),编译器会选择 const T* operator-> () const另一方面。

上面的代码示例不会以这种方式工作,所以我很好奇是否有可能为编译器提供我提到的行为。任何提议。


编辑:让我们的成员访问运算符以这种方式重载:

    const T* operator-> () const { return instance; }

    T* operator-> () {
        cout << "something going change" << endl;
        return instance;
    }

让我们有一个变量Component<DataComponent> c某处。然后调用c->getCaption() stdout 应该保持沉默但在调用 c->setCaption("foo") 时stdout 应该警告我们某些事情将会发生变化。 VS 2010 编译器让标准输出在每次调用时都向我们发出警告。

我理解这样的语义假设 c同时表现为 const 和非常量。但好奇心仍在我的脑海中。

最佳答案

调用 const 或非 const 成员完全取决于调用它的对象的常量性,而不是由某些后续操作决定。该决定是在考虑您在 DataComponent 中调用的特定方法之前做出的。您仍然可以通过 const 和非 const 转发 getCaption() 围绕 DataComponent 直接使用代理对象来破解所需的功能。

编辑:按要求提供详细信息(超出我的想象)。你需要转发声明其中的一些东西——我没有费心,因为它让它变得更加困惑。提出任何疑虑/反馈。请注意,这基本上假设您出于某种原因不能/不想修改 Component,但它不是一个通用的模板化解决方案,可以简单地围绕任意类型进行包装 - 它耦合度很高并且维护负担很高。

// know they can't call a non-const operation on T, so this is ok...
const T* Component::operator->() const { return instance; }

// they might invoke a non-const operation on T, so...
DataComponent::Proxy Component::operator->() { return DataComponent.getProxy(*this); }

DataComponent 类中:

struct Proxy
{
    Component& c_;
    DataComponent& d_;

    Proxy(Component& c, DataComponent& d) : c_(c), d_(d) { }

    const std::string& get_caption() const { return d_.get_caption(); }

    void set_caption(const std::string& s)
    {
        c_.on_pre_mutator(d_);
        d_.set_caption(s);
        c_.on_post_mutator(d_);
    }
};

然后

DataComponent::Proxy DataComponent::getProxy(Component& c) { return Proxy(c, *this); }

因此,这意味着您必须在某个地方手动编写转发功能代码。这很痛苦,但如果您这样做是为了调试或测试,那也不是没有道理的。如果您这样做是为了添加锁或其他东西,那么可能有更好的选择。

关于c++ - Const 和非常量访问解析为不同的重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3922016/

相关文章:

c++ - 以某种方式将基类的指针强制转换为未知的子类?

c++ - 附加冒号在模板类中意味着什么。类名<T, SIZE>::类名:

c++ - 如何通知一个小部件有关 Qt 中另一个小部件的更改?

c++ - Release模式下迭代器的绑定(bind)检查 (c++)

java - 使用哪种设计模式?

design-patterns - 装饰器模式的优缺点是什么?

c++ - 归并排序。使用迭代器实现

c++ - 具有参数化构造函数的二维 vector

c++ - 旋转一个 vector 以达到与另一个 vector 的正交性

javascript - 斯托扬·斯特凡诺夫 : JavaScript Patterns - "The Default Pattern"