Я думаю, что невозможно static_cast
связать Derived ссылку значения на ссылку его Base типа в методе getIdentifer
, как неявно показано в пример ковариации Стива Джессопа, потому что тогда вы будете создавать временный ссылка, но могу ошибаться. Поэтому вместо этого я сделал метод (названный getElement
), который возвращает возможно приведенный указатель, который обязательно будет существовать.
Поскольку вам может понадобиться явная связь между ContainerA
и ContainerB
(в случае дублирования кода), я написал пример на основе class
того, как вы могли бы это реализовать. В противном случае, использование шаблонной функции, вероятно, является выходом.
Если вы используете структуры, вам не нужны ни метки public
, protected
и private
, ни сеттеры для переменных, но вам, конечно, нужен некоторый метод getIdentifier
для доступа к элементам типа B
.
Вот демонстрационная программа:
A
#pragma once
#include <iostream>
class A
{
public:
A(const int& data);
friend std::ostream& operator<<(std::ostream& s, const A& a);
protected:
virtual std::ostream& toStream(std::ostream& s) const;
private:
int m_data;
};
A::A(const int& data)
: m_data{ data }
{
}
std::ostream& A::toStream(std::ostream& s) const
{
return s << m_data;
}
std::ostream& operator<<(std::ostream& s, const A& a)
{
return a.toStream(s);
}
B
#pragma once
#include "A.h"
class B : public A
{
public:
B(const int& data, const int& additionalData);
void setAdditionalData(int additionalData);
protected:
virtual std::ostream& toStream(std::ostream& s) const;
private:
int m_additinalData;
};
B::B(const int& data, const int& additionalData)
: A{ data },
m_additinalData{ additionalData }
{
}
void B::setAdditionalData(int additionalData)
{
m_additinalData = additionalData;
}
std::ostream& B::toStream(std::ostream& s) const
{
A::toStream(s);
return s << '\t' << m_additinalData;
}
Контейнер А
#pragma once
#include "A.h"
#include <vector>
class ContainerA
{
public:
void push(A* a);
size_t getSize() const;
virtual A* getElement(const int& index);
virtual A* operator[](const int& index);
protected:
std::vector<A*> m_As;
};
void ContainerA::push(A* a)
{
m_As.push_back(a);
}
A* ContainerA::getElement(const int& index)
{
return m_As[index];
}
A* ContainerA::operator[](const int& index)
{
return m_As[index];
}
size_t ContainerA::getSize() const
{
return m_As.size();
}
КонтейнерБ
#pragma once
#include "ContainerA.h"
#include "B.h" // The compiler should be able to tell that B is a subclass of A
class ContainerB : public ContainerA
{
public:
B* getElement(const int& index) override;
B* operator[](const int& index) override;
private:
int additional_data;
};
B* ContainerB::getElement(const int& index)
{
return static_cast<B*>(m_As[index]);
}
B* ContainerB::operator[](const int& index)
{
return static_cast<B*>(m_As[index]);
}
main.cpp
#include "ContainerB.h"
int main()
{
B b1{ 4, -1 };
B b2{ 5, -1 };
B b3{ 6, -1 };
ContainerB contB{};
contB.push(&b1);
contB.push(&b2);
contB.push(&b3);
B* b{ contB.getElement(0) };
b->setAdditionalData(0);
size_t size{ contB.getSize() };
for (int i{ 0 }; i < size; ++i) {
std::cout << *contB.getElement(i) << std::endl;
std::cout << *contB[i] << std::endl;
}
}
Вывод
4 0
4 0
5 -1
5 -1
6 -1
6 -1
Теперь вы можете передать ContainerB
функции/методу, который ожидает ContainerA
, без необходимости хранить избыточные данные.
person
Community
schedule
18.08.2020
ContianerB
? - person NathanOliver   schedule 18.08.2020struct ContianerB : public ContainerA
? - person goodvibration   schedule 18.08.2020ContainerA
иContainerB
и использовать его в качестве полиморфного контейнера. - person Miguel   schedule 18.08.2020getIdentifier
- person   schedule 18.08.2020share
внизу ответа. - person goodvibration   schedule 18.08.2020ContainerB
расширяетContainerA
- person Solon   schedule 18.08.2020const&
, но мне это не удалось, поэтому я решил не добавлять ответ. (Я привык иметьvirtual CoParent* Identifier()
.) Почему это связано? В случае, еслиContainterB
ведет себя какContainterA
илиstruct ContianerB : public ContainerA
, вы можете предоставитьContainerA
методvirtual A* getElement(const int& index);
и предоставитьContainerB
методB* getElement(const int& index) override;
. Таким образом, вам не нужен членstd::vector<B>
вContainerB
, потому что вы знаете, что элементыva
будут иметь типB
. - person   schedule 18.08.2020