C ++: Почему VS2005 интерпретирует прямую инициализацию локального экземпляра как функцию, когда конструктор класса имеет полиморфный параметр? - PullRequest
2 голосов
/ 04 февраля 2010

У меня есть следующий код C ++ в Visual Studio 2005 ...

class Base {};
class Derived : public Base {};

class Other {
public:
 Other(const Base& obj) {}
 void test() {}
};

int _tmain(int argc, _TCHAR* argv[])
{
 Other other(Derived());
 other.test();
 return 0;
}

... Компиляция завершается неудачно и выдает:

test.cpp(19) : error C2228: left of '.test' must have class/struct/union

Через несколько тестов я определил, что это происходит потому, что объявление переменной "other" интерпретируется как объявление функции (возвращающее Other и принимающее параметр Derived) вместо экземпляра Other, использующего конструктор аргументов. (VS6 находит конструктор и прекрасно его компилирует, но он не очень хорош в стандартном C ++, поэтому я не доверяю ему по сравнению с VS2005)

Если я сделаю ...

Other other(static_cast<Base&>(Derived()));

... или используйте инициализацию копирования, все работает нормально. Но кажется, что он не видит, что экземпляр Derived () является производным от Base сам по себе, или он отдает приоритет объявлению функции вместо попытки полиморфизма для параметра конструктора.

У меня вопрос: это стандартное поведение C ++ или это поведение, специфичное для VS2005? В случае, если ...

Other other(Derived());

... объявить локальный экземпляр в стандарте C ++ или он должен объявить функцию?

Ответы [ 3 ]

3 голосов
/ 04 февраля 2010

Да, это стандартное поведение. См. эту C ++ FAQ-lite запись .

Согласно стандарту это:

Other other(Derived());

интерпретируется как объявление функции функции, которая возвращает Other, и принимает в качестве параметра другую функцию, которая возвращает Derived и не имеет параметров. Чтобы это исправить, вы можете использовать:

Other other = Other(Derived());
2 голосов
/ 04 февраля 2010

Вы упоминаете "полиморфный параметр" в заголовке вашего вопроса, хотя на самом деле все это не имеет абсолютно никакого отношения к каким-либо полиморфным параметрам. В C ++ проблемное объявление объявляет функцию независимо от того, является ли предоставленный вами «аргумент» полиморфным или нет.

Как обычно, вы можете использовать дополнительную пару (), чтобы обойти проблему

Other other((Derived())); // now it is an object, not a function

Вы также можете использовать любой другой метод, чтобы превратить часть Derived() в выражение, например

Other other((const Derived&) Derived()); 

или

Other other(((void) 0, Derived())); 
1 голос
/ 04 февраля 2010

Я попробовал ваш пример в VS2008 и GCC, и это тоже происходит там.

На что это похоже, так это то, что этот синтаксис фактически объявляет other как указатель на функцию с помощью этого объявления:

Other other(Derived (*)(void))

Правильное поведение должно использовать инициализацию:

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