Как использовать значение унаследованного члена класса при повышении до базового класса - PullRequest
1 голос
/ 05 мая 2020

У меня проблема с отображением содержимого унаследованных членов класса при приведении к базовому классу. В настоящее время отображается результат 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;
} 

Ответы [ 3 ]

4 голосов
/ 05 мая 2020

Как использовать значение унаследованного члена класса при повышении до базового класса

Используя полиморфизм времени выполнения. Напишите виртуальную функцию.

В этом случае может быть уместен виртуальный перегруженный оператор индекса:

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;
3 голосов
/ 05 мая 2020

Наличие члена одного и того же типа и имени в основе и производном не является неправильным, но у меня такое чувство, что вы не знаете о последствиях. Объект 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

Если вы хотите, чтобы B инициализировал член v с помощью {1,2,3}, вы можете сделать две вещи : Предоставьте конструктор для 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, но по возможности следует избегать применения забросов. Вместо этого базовый класс должен предоставлять необходимый интерфейс.

0 голосов
/ 05 мая 2020

Что происходит, так это то, что у вас есть два разных поля A :: v и B :: v. И при доступе к v извне он достигнет поля в производном классе (обратите внимание, эти два поля не имеют ничего общего друг с другом - они могут быть, например, разных типов.)

Чтобы действительно достичь базового поля v , вы бы сделали

obj->A::v[1];

Однако знайте, действительно ли это то, что вы хотите. Не зная больше, трудно сказать наверняка, но это похоже на несовершенный дизайн.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...