C ++ приведёт объект к исходному типу - PullRequest
1 голос
/ 28 марта 2020

Чего я хочу добиться, это следующее поведение:

int main(){
   vector<Component*>v = {...};
   draw(dynamic_cast< ??? >v[0]);
}
 void draw(const Image& i){...}
 void draw(const Text& i){...}
 void draw(const Link& i){...}

, где Image, Text, Link являются производными классами от Component, но я не знаю, что поместить в < > Dynami c cast, или, по крайней мере, если есть другой способ сделать это.

На данный момент я думал о том, чтобы использовать variant, но чтобы получить элемент, мне нужно вызвать std::get где мне нужно указать тип, и так в той же точке.

Так что на данный момент я думаю, что единственный способ - это создать список if(dynamic_cast<>(v[0]) со всеми возможными типами ...

Ответы [ 3 ]

3 голосов
/ 28 марта 2020

Нечего приводить, потому что vector<Component> может содержать только объекты типа Component. Он не может содержать никаких производных объектов. Тип Stati c может отличаться от типа Dynami c только косвенным путем.

Теперь, если бы у нас был случай, когда у вас была ссылка, например, на базовый класс, во время компиляции не было бы никакого способа чтобы знать тип динамического c, таким образом, нет ничего, что вы могли бы записать в dynamic_cast<???>, что сделало бы эту работу.

Способ, которым полиморфизм динамического c достигается посредством наследования, состоит в том, чтобы вместо этого передать ссылку основываться на функции draw, а затем использовать виртуальные функции-члены Component, чтобы иметь различное поведение в зависимости от типа Dynami c.

1 голос
/ 28 марта 2020

Если вы в конечном итоге используете variant, вы можете использовать std::visit, чтобы определить, какую форму вашей функции рисования вызывать, если вам не нужны другие аргументы, или они все принимают те же аргументы после тип:

for ( auto & vitem : in v ) // where v is a vector of variant
  std::visit([](auto && shape){ draw( shape ); }, vitem);

Подробнее см. https://en.cppreference.com/w/cpp/utility/variant/visit.

1 голос
/ 28 марта 2020

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

void draw(const Image& i) { ... }
void draw(const Text& i) { ... }
void draw(const Link& i) { ... }

int main() {
   vector<Component*> v = {...};
   ...   
   if (Image *img = dynamic_cast<Image*>(v[0]))
      draw(img);
   else if (Text *txt = dynamic_cast<Text*>(v[0]))
      draw(txt);
   else if (Link *lnk = dynamic_cast<Link*>(v[0]))
      draw(lnk);
   ...
}

Излишне говорить, что это не очень хороший подход. Вместо этого draw() должен быть virtual методом Component, и тогда каждый подкласс может override его при необходимости, например:

class Component
{
public:
   ...
   virtual void draw() { ... }
   ...
};

class Image : public Component
{
public:
   ...
   void draw() override { ... }
   ...
};

class Text : public Component
{
public:
   ...
   void draw() override { ... }
   ...
};

class Link : public Component
{
public:
   ...
   void draw() override { ... }
   ...
};

int main() {
   vector<Component*> v = {...};
   ...   
   v[0]->draw();
   ...
}
...