Конструктор не возвращает полезный объект - PullRequest
7 голосов
/ 19 марта 2011

У меня проблема с конструктором, который работает не так, как я ожидал.

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

vector<float> v;
MyClass<2> a(v);

Однако, если я попытаюсь создать класс, как показано ниже (который должен быть эквивалентен), результаты будут довольно неожиданными. При компиляции или запуске программы нет сообщений об ошибках или предупреждений. Но если вы попытаетесь использовать эту переменную где-нибудь и вызвать ее методы (например, a.doSomething ()), она потерпит крах.

Я поместил некоторый код в конструктор, чтобы уведомить меня, если он используется. Оказалось, что в этом случае код внутри конструктора фактически не выполнялся.

MyClass<2> a(vector<float>());

Так что мне интересно, почему это происходит? 2-я декларация незаконна?

РЕДАКТИРОВАТЬ: я опубликую некоторый код класса

template <int x>
class MyClass {
public:
    vector<float> v;
    MyClass<x>(vector<float> v1) {
      v = v1;
    }

};

1 Ответ

18 голосов
/ 19 марта 2011
MyClass<2> a(vector<float>());

Это не объявление переменной. Это объявление функции с именем a, которая возвращает объект MyClass<2> и принимает в качестве аргумента «указатель на функцию, которая не принимает аргументов и возвращает vector<float>». Смешение? Да. Это то, что называется "самым неприятным разбором".

Вам нужны дополнительные скобки:

MyClass<2> a((vector<float>()));
             ^               ^

Или вы можете использовать инициализацию копирования:

MyClass<2> a = MyClass<2>(vector<float>());

Или, поскольку ваш конструктор не explicit, вы можете использовать:

MyClass<2> a = vector<float>();

(Хотя, если вы не хотите, чтобы объекты vector<float> были неявно преобразованы в MyClass<N> объекты, вы, вероятно, захотите сделать этот конструктор explicit.)


Хороший компилятор должен предупреждать вас о подобных вещах. Visual C ++ предупреждает:

предупреждение C4930: 'MyClass<x> a(std::vector<_Ty> (__cdecl *)(void))': прототипная функция не вызывается (было ли предназначено определение переменной?)

Clang предупреждает:

предупреждение: круглые скобки были устранены в качестве объявления функции

MyClass<2> a(vector<float>());
            ^~~~~~~~~~~~~~~~~
...