简体   繁体   中英

How to use value of inherited class member, when upcasting to base class

I have a problem with displaying the content of inherited class members, when up casting to the base class. Currently, the result displayed is 4 , how can I achieve 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;
} 

How to use value of inherited class member, when upcasting to base class

By using runtime polymorphism. Write a virtual function.

In this case, a virtual overloaded subscript operator might be appropriate:

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};
};

Usage:

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

Having member of same type and name in the base and the derived is not wrong, but I have the feeling that you are not aware of the consequences. A B object has two members called v . For illustration consider this example:

#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;
} 

Output is: 53

If you want B to initialize the member v with {1,2,3} then you can do two things: Provide a constructor for A that initializes the member, and call that constructor in 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];
}  

Output: 1

To answer your question literally:

How to use value of inherited class member, when upcasting to base class

Usually you should not access members of a derived class directly when you have a pointer to base class. It is possible via a dynamic_cast but casts should be avoided when possible. Instead the base class should provide the necessary interface.

What happens is that you have two different fields A::v and B::v. And when accessing v from outside it will reach the field in the derived class (note, these two Fields has nothing to do with eachother - they can be different types for instance.)

To actually reach the base v field, you would do

obj->A::v[1];

However, be aware if this is actually what you want. Without knowing more, it is hard to say for certain, but it looks like flawed design.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM