向上转换到基类时如何使用继承的类成员的值

Posted

技术标签:

【中文标题】向上转换到基类时如何使用继承的类成员的值【英文标题】:How to use value of inherited class member, when upcasting to base class 【发布时间】:2020-05-05 17:09:24 【问题描述】:

在投射到基类时,我在显示继承的类成员的内容时遇到问题。目前显示的结果是4,如何才能达到2

#include <iostream>
#include <vector>
#include <memory>
#include <tuple>

class A 
public:
  A() = default;  
  std::vector<int> v = 3, 4, 5;
;

class B : public A 
public:
    B()  v = 1, 2, 3; 
    std::vector<int> v = 1, 2, 3;
;

int main() 
   std::vector<std::tuple<std::shared_ptr<A>, int>> v = 
        std::make_tuple<std::shared_ptr<A>, int>(std::make_shared<B>(), 5) 
    ;

    std::shared_ptr<A> obj;
    std::tie(obj, std::ignore) = v[0];
    std::cout << obj->v[1] << std::endl;
 

【问题讨论】:

你能解释一下为什么吗?您不应通过指向A 的指针访问B 的成员。 AB 都有一个同名的成员,这有点奇怪。您知道B 中的vs 都存在吗?您是否可能更希望 B1,2,3 初始化 As v 你想要这个:godbolt.org/z/KfC2KN 吗? 其实只是为了学习。我不知道我是否觉得这很有用或者这是个好主意;)是的,你解决了我的问题。我现在也可以写这个了:coliru.stacked-crooked.com/a/e76166a0609a0a17 【参考方案1】:

向上转换到基类时如何使用继承类成员的值

通过使用运行时多态性。写一个虚函数。

在这种情况下,虚拟重载下标运算符可能是合适的:

struct A 
    virtual int& operator[](std::size_t index) = 0;
;

struct B : A 
    int& operator[](std::size_t index) override 
        return v[index];
    

    std::vector<int> v = 1, 2, 3;
;

用法:

std::cout << obj[1] << std::endl;

【讨论】:

嗯,没有考虑过这种可能性。 +1【参考方案2】:

在基类和派生类中具有相同类型和名称的成员并没有错,但我感觉你没有意识到后果。 B 对象有两个名为 v 的成员。为了便于说明,请考虑以下示例:

#include <iostream>

struct A  int x = 3; ;    
struct B : A  int x = 5; ;

int main() 
    B b;
    std::cout << b.x;
    std::cout << b.A::x;
 

输出为:53

如果您希望B1,2,3 初始化成员v,那么您可以做两件事:为A 提供一个初始化该成员的构造函数,并在B 中调用该构造函数:

#include <iostream>
#include <vector>

class A 
public:
  A() = default;  
  A(std::vector<int> v) : v(v) 
  std::vector<int> v = 3, 4, 5;
;

class B : public A 
public:
    B() : A(1,2,3) 
;

int main() 
    B b;
    std::cout << b.v[0];
  

输出:1

从字面上回答你的问题:

向上转换到基类时如何使用继承类成员的值

当你有一个指向基类的指针时,通常你不应该直接访问派生类的成员。可以通过dynamic_cast 进行,但应尽可能避免强制转换。相反,基类应该提供必要的接口。

【讨论】:

【参考方案3】:

发生的情况是您有两个不同的字段 A::v 和 B::v。而当从外部访问 v 时,它将到达派生类中的字段(注意,这两个字段彼此无关 - 例如它们可以是不同的类型。)

要真正到达基本 v 字段,您会这样做

obj->A::v[1];

但是,请注意这是否真的是您想要的。不知道更多,很难确定,但它看起来像有缺陷的设计。

【讨论】:

以上是关于向上转换到基类时如何使用继承的类成员的值的主要内容,如果未能解决你的问题,请参考以下文章

当有多个派生类时,如何使用基类指针访问派生类的函数成员?

如何在基类的函数上使用装饰器并在继承基类时让装饰器在该函数上工作

C++继承

为啥我的性能慢到爬行我将方法移动到基类中?

继承基类时如何避免错误“找不到类型'MyType'的构造函数”

C++多继承