如何仅将基类公开为 const 引用

How to expose a base class only as const reference

提问人:Daniel Bauer 提问时间:3/1/2023 最后编辑:Daniel Bauer 更新时间:3/1/2023 访问量:112

问:

我希望我的类仅将其基类公开为对 的常量引用。这意味着可以读取 的成员,但不能设置。 这是我尝试过的:FooBarBarBar

struct Bar
{
    int member;
};

class Foo : protected Bar
{
public:
    operator const Bar&() { return *this; }
};

但是当使用它时,会出现以下问题:

int getBarMember( const Bar& bar )
{
    return bar.member;
}

int main()
{
    Foo myFoo;

    const Bar& refBar = myFoo; // C2243
    // const Bar& refBar = (const Bar&) myFoo; // always need to cast explicitly

    int read = refBar.member;

    int readByFunction = getBarMember( myFoo ); // C2243
    // int readByFunction = getBarMember( (const Bar&) myFoo ); // always need to cast explicitly
}

我希望能够在没有显式强制转换的情况下调用接受常量引用的函数。Bar

编译器错误为:

C2243:存在从“Foo *”到“const Bar&”的“转换类型”转换,但 无法

C++ 继承 const-correctness

评论

1赞 Yksisarvinen 3/1/2023
每个人都会理解“const reference to”,即使它不是 100% 精确。不用担心。
2赞 463035818_is_not_an_ai 3/1/2023
没有混淆的危险,因为引用是隐式的常量,你不能重新绑定它们。通俗地说,“const reference”和“reference to const”之间没有区别,至少我不知道
1赞 463035818_is_not_an_ai 3/1/2023
我建议公开,阅读错误消息并发布。目前看来,这可以作为错别字关闭,但不仅仅是错别字。目前,错误是由于您的操作员是 ,但这是小问题operator Barprivate
1赞 463035818_is_not_an_ai 3/1/2023
请不要将工作代码与需要删除的代码的错误混为一谈。为了重现错误而必须对代码进行的任何更改都是误解和混淆的根源。最好是发布重现错误的代码和逐字完成编译器错误消息//
1赞 463035818_is_not_an_ai 3/1/2023
我的意思是:godbolt.org/z/9TaaMx3TK 没有错误。现在,不同的编译器会生成不同的错误消息。我必须非常幸运地找到相同的编译器、版本并删除确切知道你在说什么的权利//

答:

5赞 Yksisarvinen 3/1/2023 #1

我认为这是不可能的,gcc 和 clang 对操作员发出以下警告:

<source>:12:5: warning: converting 'Foo' to a reference to a base class 'Bar' will never use a type conversion operator [-Wclass-conversion]
  12 |     operator const Bar&() { return *this; }
     |     ^~~~~~~~

如果在实际代码中可行,则可以使用组合而不是继承原则并执行以下操作(在线查看):

struct Bar
{
    int member;
};

class Foo 
{
public:
    operator const Bar&() { return parent; }
protected:
    Bar parent;
};

它可能需要对内部的访问方式进行一些更改,但它可以在没有外部世界强制转换的情况下工作。BarFoo

评论

0赞 Daniel Bauer 3/1/2023
表达它们之间关系的非常好的替代方式,我现在将在我的应用程序中使用它。