【问题标题】:Is const_cast on pointer to member safe?指向成员的指针上的 const_cast 是否安全?
【发布时间】:2014-09-02 12:53:35
【问题描述】:

在下面的代码中,一个对象的非const方法调用了同一个对象的const方法,该方法返回一个指向对象字段的const指针,然后这个返回的指针被强制转换为非const 版本——这是一种类似于此答案中的技术:Elegant solution to duplicate, const and non-const, getters? [duplicate]。但是,由于我将指针放入复杂的数据结构中,我不确定它是否真的有效。会吗?

class Struct {
private:
    Field f, g;

    std::map<std::string, const FieldBase*> const_fields_t;
    std::map<std::string, FieldBase*> fields_t;

public:
    const_fields_t get_fields() const {
        return const_fields_t { { "f", &f }, { "g", &g } };
   }

   fields_t get_fields() {
        const Foo* = this;
        fields_t result;

        foreach(auto& v : const_this->get_fields()) {
            result[v->first] = const_cast<FieldBase*>(v->second);
        }
        return result;
   }
};

【问题讨论】:

  • 它会起作用,但我认为仅用于具有 const-non-const 复制的深复制容器有点开销。
  • 你可以这样做,但在上面的代码中还有一些其他的事情需要解决。

标签: c++ pointers constants const-cast


【解决方案1】:

是的,(我稍微清理了你的代码):

#include <string>
#include <functional>
#include <iostream>
#include <map>
using namespace std;

class FieldBase {public: virtual string get_data() = 0; };
class Field : public FieldBase { public: string data; virtual string get_data() { return data; } };

class Struct {
public:
    Field f, g;

    typedef std::map<std::string, const FieldBase*> const_fields_t;
    typedef std::map<std::string, FieldBase*> fields_t;

public:
    const_fields_t get_fields() const {
        cout << "const get_fields() called" << endl;
        return const_fields_t { { "f", &f }, { "g", &g } };
   }

   fields_t get_fields() {
        cout << "non-const get_fields() called" << endl;
        auto const_this = static_cast<const Struct*>(this);
        fields_t result;

        for(auto& v : const_this->get_fields()) {
            result[v.first] = const_cast<FieldBase*>(v.second);
        }
        return result;
   }
};

int main ()
{
    Struct a;
    a.f.data = "Hello";
    a.g.data = "World";

    Struct::fields_t obj = a.get_fields();

    cout << obj["f"]->get_data() << endl;
    cout << obj["g"]->get_data() << endl;

}

Live example

您基本上让const 函数充当网关,以获取您需要的值,然后抛弃常量。这也适用于您的目的,因为指针将被解构并存储在新地图中。

请记住,可能有更好的解决方案不涉及上述所有复制。

【讨论】:

  • 嗯,一个想法是缓存这两个地图(在构造函数中调用get_fields(),将结果存储在两个字段中),但是移动/复制构造函数变得不平凡。而且由于我打算将Struct 用作基类(get_fields() const 是纯虚拟的),这可能会导致一些问题...
  • 这一切愚蠢的根源在于std::map&lt;K, V&gt;std::map&lt;K, const V&gt;完全不相关,不像V (*)(K)const V (*)(K)
  • 如果我理解正确并且您计划通过构造函数使用虚函数,请注意一些东西 (stackoverflow.com/a/25562868/1938163)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-24
  • 1970-01-01
  • 2013-05-02
  • 1970-01-01
  • 2021-12-03
  • 2023-03-12
相关资源
最近更新 更多