2016-12-15 38 views
0

У меня есть эта ошибка компиляции no matching function for call to ‘Color::Color(Component&)’ на этом шаблонном методе:Ошибка компиляции: «нет функции соответствия для вызова» при возвращении static_cast ссылки

template<typename U> 
inline U& getObject(const std::string& key) 
    { 
    return (static_cast<U>(*(_map.at(key)))); 
    } 

Я называю это так (компоненты есть мой типа, содержащие мою карта):

components.getObject<Color>("Color").getColor();

Цвет наследоваться от компонента и _MAP является отображением строки и Компонент * (указатель на компонент).

У меня есть много типов, исходящих из Component, и я сохраняю указатель на них на моей карте. Но когда я пытаюсь получить Компонент с карты и применить его к определенному типу, чтобы использовать его, я получаю ошибку компиляции выше. Я не понимаю, почему.

+1

Попробуйте статическое кастинг на U & –

+0

Черт, что сработало, я не могу поверить, что я не об этом, спасибо, очень много, мне пора спать – Roger

+0

@Redleouf, это была опечатка или вы не думали что в качестве возможного ответа, когда вы разместили q uestion? –

ответ

2

I have a lot of types derivating from Component and I store a pointer to them in my map. But when I try to get a Component from the map and cast it to a specific type to use it, I get the compile error above. I don't understand why.

Потому что ваша функция закодирована неправильно.

Ваша функция извлечение Component* указателя на карте, разыменование указателя для доступа только Component части объекта (не полный производного типа), а затем пытается построить временный экземпляр производного класса с входом Component.

Другими словами, ваш пример, по существу, как это сделать:

inline Color& getObject(const std::string& key) 
{ 
    TComponent *pcomp = _map.at(key); 
    Color tmp(*pcomp); // <-- error here 
    return tmp; 
} 

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

Даже если код сделал компиляции, он все равно будет неправильно, потому что вы возвращаете ссылку на временный объект, который разрушается при выходе из нее, так что абонент будет в конечном итоге с висячей ссылкой на недействительных памяти ,

Как указано @MikeVine в комментариях, вы можете написать функцию, как это исправить:

template<typename U> 
inline U& getObject(const std::string& key) 
{ 
    return static_cast<U&>(*(_map.at(key))); 
} 

И это будет работать, так как он исключает строительство временного объекта, и возвращает ссылку на существующий объект, сохраненный на карте.

Вы также могли бы написать функцию, как это вместо:

template <typename U> 
inline U& getObject(const std::string& key) 
{ 
    return *(static_cast<U*>(_map.at(key))); 
} 

Этот код бросает Component* указатель на U* указатель первого до этого разыменования для доступа к производный объект класса.

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

template <typename U> 
inline U& getObject(const std::string& key) 
{ 
    U *ptr = dynamic_cast<U*>(_map.at(key)); 
    if (!ptr) throw std::invalid_argument(""); 
    return *ptr; 
} 

В качестве альтернативы:

template<typename U> 
inline U& getObject(const std::string& key) 
{ 
    return dynamic_cast<U&>(*(_map.at(key))); 
}