当前位置: 首页 > 知识库问答 >
问题:

代理对象的常量正确性

辛盛
2023-03-14

我对下面的代码感到困惑,其中类baz通过代理类bar授予对其内部数据的访问权限:

struct Foo{};

template<class T>
struct Bar 
{
    Bar(T &val_): val(val_) {}

    T &val;
};

struct Baz 
{
    Bar<const Foo> get() const {return Bar<const Foo>(foo);}
    Bar<Foo>       get()       {return Bar<Foo>      (foo);}
    Foo foo;
};

struct FooBaz
{
    FooBaz(Baz &baz_): baz(baz_) {}
    // Bar<const Foo> get() const {return baz.get();} // this do not compile
    Bar<const Foo> get() const {return const_cast<const Baz &>(baz).get();} // the const_cast seems to be required
    Baz &baz;
};

似乎我必须执行一个const_cast来分派到正确的baz::get()函数。

我不明白的第一件事是,如果foobaz::baz是一个普通的baz而不是一个引用,那么它可以工作:

struct Foo{};

template<class T>
struct Bar 
{
    Bar(T &val_): val(val_) {}

    T &val;
};

struct Baz 
{
    Bar<const Foo> get() const {return Bar<const Foo>(foo);}
    Bar<Foo>       get()       {return Bar<Foo>      (foo);}
    Foo foo;
};

struct FooBaz
{
    FooBaz(Baz &baz_): baz(baz_) {}
    Bar<const Foo> get() const {return baz.get();} // Ok
    Baz baz;
};

我对const函数成员的理解是,它使这个成为const的指针,但实际上我并不完全清楚它的含义。。。 所有的数据成员都是‘就像它们是常量’吗? 对此有明确的提法吗?

另一件有趣的事情是,如果我使用std::reference_wrapper作为代理类,那么它在没有const_cast:

#include <functional>

struct Foo {};

struct Baz 
{
    std::reference_wrapper<const Foo> get() const {return std::cref(foo);}
    std::reference_wrapper<Foo>       get()       {return std::ref (foo);}
    Foo foo;
};

struct FooBaz
{
    FooBaz(Baz &baz_): baz(baz_) {}
    std::reference_wrapper<const Foo> get() const {return baz.get();} // Ok
    Baz &baz;
};

std::reference_wrapper有什么神奇之处?

谢啦!

共有2个答案

景宏朗
2023-03-14

我必须执行一个const_cast来分派到正确的baz::get()函数。

是的。 或std::as_const,或使Bar<;t>可转换为Bar<;constT>

我对const函数成员的理解是,它使this指针指向const,但实际上我并不完全清楚它的含义。。。 所有的数据成员都是‘就像它们是常量’吗?

是的,成员的行为就像是常量

表达式e1->e2完全等同于内置类型的(*e1).e2; 这就是为什么下面的规则只处理E1.E2

在表达式E1.E2中:

如果E2是非静态数据成员:

如果E2是引用类型T&;T&;,则结果是T类型的L值,指定E2引用的对象或函数,否则,如果E1是L值,则结果是指定E1的非静态数据成员的L值,否则(如果E1是xvalue(可从prvalue物化)),则结果是指定E1的非静态数据成员的xvalue。

如果e2不是可变成员,则结果的CV限定条件是e1e2的CV限定条件的并集,否则(如果e2是可变成员),则结果的CV限定条件是e1e2的Volatile限定条件的并集;

-cp首选项

当通过指向const类的指针访问时,其成员变为const

但恒常性只在顶层添加。 如果通过指向const的指针访问int*const member;,则它将成为int*const member;,而不是const int*const member;

引用以类似的方式工作,但是因为引用本身不能是const1,所以它们的类型不会改变。

如果我使用std::reference_wrapper作为代理类,那么它在没有const_cast的情况下工作

这是因为它有一个构造函数,允许从std::reference_wrapper 构造std::reference_wrapper

1是的,引用在创建后不能更改为指向其他对象,但形式上它不是常量std::is_const返回引用的false

丌官哲彦
2023-03-14

如果foobaz::baz是普通的baz而不是引用,则可以工作:

这才是重点。 在const成员函数中,数据成员也被视为const。 请注意,对于引用,这意味着引用成员本身,而不是被引用的对象。 即baz将变成baz&; 常量baz;(常量引用),而不是baz常量& baz;(引用常量)。 事实上,引用不能进行常量限定,常量限定符只是被忽略,因为即使在const成员函数中,baz.get();也始终调用非常量的get()

对于std::reference_wrapper版本,它没有改变,baz.get();仍然调用非常量get()并返回std::reference_wrapper std::reference_wrapper具有转换构造函数,因此,转换后的std::reference_wrapper 存储对从std::reference_wrapper 获得的对象的引用(通过转换运算符)。

 类似资料:
  • 问题内容: 以上失败,并出现AttributeError异常。我了解Python在调用时不保证 “全局变量”(在这种情况下是否存在成员数据)的存在。如果是这种情况,并且这是导致异常的原因,那么如何确保对象正确销毁? 问题答案: 我建议使用Python的语句来管理需要清理的资源。使用显式语句的问题在于,你必须担心人们会忘记完全调用它,或者忘记将其放在块中以防止发生异常时发生资源泄漏。 要使用该语句,

  • 所以我的问题是,为什么交易未能将它从Hibernate代理转换为真正的对象?而且,如果我从上面的注释中删除(fetch=fetchtype.lazy)部分,这是一个变通方法吗?不过,我不愿意这样做,因为上面的代码实际上在Measure的父类中,它可能会对其他代码产生连锁反应。(为了更简单的说明,我移动了贸易属性来度量)。

  • 我正在使用Xamarin和MVVMCross开发一个应用程序,在创建绑定NSLayoutConstraints常量时遇到问题。 我有一个带有子视图的视图,如果某个列表 为此,我向该视图添加了一个NSLayoutConstraint,以便能够以编程方式修改其高度,并使用以下代码行对其进行绑定: CountToConstraintHeightConverter非常简单,它只检查值是否等于0以返回0或默

  • 问题内容: 我正在寻找将方法调用从对象(包装器)传递到对象(包装器)的成员变量的方法。可能有许多方法需要外部化,因此在将方法添加到包装中时,无需更改包装器接口即可做到这一点。 如果此呼叫重定向是“快速”的(相对于直接呼叫,即不增加太多开销),那将是很好的。 问题答案: 一个比较优雅的解决方案是在包装类上创建“属性代理”: 所有的魔术都发生在类的方法上,该方法将尝试访问实例上的方法或属性,如果不存在

  • 这是在一次采访中问我的。 我回答他说,对于相同的输入集,父母和孩子都应该产生相同的输出集。如果子节点想要扩展父节点的功能,它应该只在父节点支持范围之外的新输入上执行。这样,孩子将维持其父母签订的合同。 我给他举了一个例子,一个api可能正在使用这样的父级 如果这个孩子在这里产生了不同的输出,那么这个孩子就违反了它的父母签订的合同。 他对我的回答不满意,并告诉我这是简单的压倒一切,不违反LSP。所以

  • 每次当我试图从他们的源代码中编译一些没有提供makefile的应用程序时(他们没有提供makefile的原因可能是它对普通用户来说是开箱即用的),我想把所有的文件都放在目标文件中然后将所有目标文件合并为二进制文件。 例如: 我发现的问题通常是,通过这种方法,必须多次运行第一个命令,以确保所有文件都已正确转换为对象文件。以前的调度失败可能是由依赖项引起的,即某些对象文件只能在创建其他对象文件后才能创

  • 这是一个子类 这是另一个子类 我最终想要的是这样的: 这不仅表示:不能分配最后一个字段dog.animalnumber,而且我认为它也行不通。有什么建议吗? 提前感谢!

  • 问题内容: 我一直在概念上为我的项目决定异常处理结构。 假设您有一个示例: 还有两个子类FileData和StaticData,它们从某些指定的文件中读取数据,StaticData仅返回一些预定义的常量数据。 现在,在读取文件时,可能会在FileData中引发IOException,但是StaticData将永远不会抛出。大多数样式指南建议在调用堆栈上传播Exception,直到有足够的上下文可以