Перегрузка на основе специализации в C ++ - PullRequest
0 голосов
/ 08 января 2010

Я пытаюсь создать функцию, которая перегружена на основе специализации ее параметра, например:

class DrawableObject...;
class Mobile : public DrawableObject...;

class Game
{
    AddObject(DrawableObject * object)
    {
        // do something with object
    }
    AddObject(Mobile * object)
    {
        AddObject(dynamic_cast<DrawableObject *>(object));
        DoSomethingSpecificForSpecializedClass();
    }
};

... но мой компилятор MS выдает мне эту ошибку:

ошибка C2681: «Мобильный *»: недопустимый тип выражения для dynamic_cast

Оба класса имеют виртуальные функции. Это неправильный актерский состав для повышения в этой ситуации? Я попробовал с броском стиля C, и все функционирует как предназначено. Кроме того, есть ли потенциальные ямы с этим дизайном?

Ответы [ 5 ]

4 голосов
/ 08 января 2010

Для явного апскейтинга используйте static_cast.

Ваш дизайн должен работать нормально.Имейте в виду, что вызовы AddObject() будут неоднозначными, если вы попытаетесь передать объект, который может быть неявно преобразован в Mobile* и DrawableObject*, например указатель на класс, производный от Mobile.

1 голос
/ 08 января 2010

Как сказал Нейл , актерский состав просто неверен. dynamic_cast<> предназначено для понижения от базы к производной, а не наоборот. Лучшим подходом является выделение общего кода, например:

class Game {
protected:
    void commonAddObject(DrawableObject *obj) {
        // do common stuff here
    }
public:
    void addObject(DrawableObject *obj) {
        commonAddObject(obj);
        // do DrawableObject specific stuff here
    }
    void addObject(MobileObject *obj) {
        commonAddObject(obj);
        // do MobileObject specific stuff here
    }
};

или для создания отдельных методов для DrawableObject и MobileObject, которые не зависят от перегрузки по типам. Я предпочитаю держаться подальше от кастинга, если смогу.

0 голосов
/ 08 января 2010

Апкастинг всегда бесплатен и безопасен. Это означает, что вам не нужно использовать защищенный dynamic_cast. Static_cast будет правильным способом сделать это, хотя приведение в стиле c также будет работать. В действительности вы должны иметь возможность покончить со второй функцией AddObject, потому что, если вы передадите указатель на объект Mobile в функцию DrawableObject, он вызовет соответствующую функцию без необходимости приведения. Если вы не планируете добавлять специализированные функции в перегруженную функцию, я бы не стал ее писать.

0 голосов
/ 08 января 2010

... или полностью удалите перегрузку AddObject (Mobile * object). Без этой функции она будет «неявно приведена» к своему базовому классу, и была бы вызвана функция AddObject (DrawableObject *). Вам не нужно вручную добавлять перегрузку и приведение для каждого типа в вашей иерархии.

Редактировать Код был добавлен, я хочу уточнить некоторые предложения о вашем дизайне.

Либо ваш класс "Game" обрабатывает все объекты одинаково, либо нет. Если это не так, нет смысла предоставлять универсальную перегрузку AddObject, которая является общедоступной - вы уже тесно связаны с отдельными объектами, так что вы могли бы также отбросить ее и шарад слабо связанной конструкции. Вы все еще можете использовать его как частную вспомогательную функцию AddObjectInternal. Поскольку это не перегрузка, вам не понадобится приведение для устранения неоднозначности вызова.

Если вы планируете или хотите обрабатывать все объекты единообразно, рассмотрите возможность использования такой логики, которую вы в настоящее время вносите в перегрузки AddObject, в виртуальные функции класса объектов. Тогда у вас есть только один метод AddObject, который вызывает виртуальные функции для добавленного объекта.

0 голосов
/ 08 января 2010

Приведение неверное и совершенно ненужное - Mobile уже является DrawableObject.

...