父级的子属性 - 访问权限
Child attribute from parent - access
给定一个函数,参数为 x 的父类 A 和类 B 从 A 继承的子类,当它是B 对象时,如何正确访问 x 的属性?前面的描述示例如下。
--编辑--
class A {
}
class B : public A {
public:
int foo;
}
void bar(A foo_){
cout << foo_.foo << endl;
}
int main(){
// Previous code:
// A a{};
// bar(a);
// Current code:
B b{}; // @O'Neil: B b(); will lead to the most vexing parse problem
bar(b);
}
--编辑--
我衷心感谢您的帮助。
b
传递到bar()
而不更改任何其他内容,则bar()
只能访问其参数中的A
,这个问题称为对象切片。解决方案是通过引用或指针将b
传递到bar()
中,即使参数的类型是 A
您可以使用dynamic_cast<>
尝试返回到派生对象。
按如下方式传入:
bar(&b);
并像这样重写bar
:
void bar(A *foo_)
{
B *foo_as_B = dynamic_cast<B *>(foo_);
if (foo_as_B != nullptr)
{
cout << foo_as_B->foo << endl;
}
}
然后它就会起作用。
dynamic_cast<>
能够将对超类的指针/引用转换为对子类的指针/引用,前提是超类对象最初实际上是作为子类实例化的。 它实际上比这要复杂一些,但仅供入门使用就足够了。
在指针情况下,如果强制转换正常,则会获得有效的指针。 如果无法完成强制转换,指针版本将返回 nullptr。 因此,在使用前检查它的原因。
好的防御性编码说你应该始终检查来自未知来源的指针。 尽管你可能相信这个cast会成功,而且你在编写bar((的时候可能是对的,但在生产代码中,完全有可能其他程序员会在两三年后出现并添加以下内容:
class C : public A
{
....
}
C c{};
bar(&c);
此时,您对 nullptr 的检查将使您免于未定义行为的恶魔。
您也可以使用引用来执行此操作,但此处的失败情况有所不同:它会引发异常,您可能希望捕获该异常。
这个问题显示了这方面的细节。
--编辑--
作为对有关获取错误C2683: 'dynamic_cast': 'A' is not a polymorphic type
的说明的回应,这个SO问题解释了原因。 该标准规定,必须至少有一个虚函数才能dynamic_cast<>
工作,这就是多态性的含义。
我从来没有遇到过这个问题,因为现在对我来说,在生产代码中使所有析构函数都虚拟是一种反射操作。 为什么要使析构函数虚拟是一个完全独立的主题,我不打算在这里深入探讨。 可以说,它确实有其优势。
综上所述,解决方法是更改class A
如下所示:
class A
{
public:
virtual ~A() {}
};
根据此链接,它应该从基础到多态类的派生指针工作,并且它确实属于 RTTI,但仍然绊倒错误。
线程的最终解决方案可以在这里找到。感谢所有参与者。
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 用于访问容器<T>数据成员的正确 API
- 访问者访问变体并返回不同类型时出错
- 尝试通过多个向量访问变量时,向量下标超出范围
- 无法访问嵌套类.类的使用无效
- 写入位置0x0000000C时发生访问冲突
- 我们可以访问一个不存在的联盟的成员吗
- C++从另一个类访问公共静态向量的正确方法是什么
- 我的简单if-else语句是如何无法访问的代码
- 使用 CTRP 时,是否访问访问父构造函数 UB 中的子属性?
- Lambda 函数,用于调用有权访问类成员的成员函数
- 使用QtCreator,如何在我有权访问ssh的远程服务器上构建我的项目?
- 默认赋值运算符有权访问基类的私有成员
- 访问接口的私有继承如何允许可访问对象访问访问私有访问实现
- 外部必须有权访问类构造函数
- 检查用户名是否有权访问窗口上的文件夹
- 获取从基类指针到具有不同类型的两个派生成员变量的访问权
- 好友有权访问好友的成员,但似乎无法更新好友的成员