C ++ - вызов методов извне класса - PullRequest
0 голосов
/ 28 октября 2009

У меня есть пара вопросов относительно некоторых правил C ++.

  1. Почему я могу вызывать функцию / метод вне класса в пространстве имен, когда я включаю тип возвращаемого значения? (посмотрите на пространство имен test2 :: testclass2 в приведенном ниже коде), т.е. это работает:

    bool b = testclass1::foo<int>(2);
    

    тогда как это не так: - (он даже не компилируется - компилятор выдает, что это переопределение функции)

    testclass1::foo<int>(2);
    

    C ++ жалуется, что это переопределение функции. Это так?

  2. Эта строка:

    bool b = testclass1::foo<int>(2);
    

    вызывается первым, прежде чем что-либо еще. Это потому, что статические методы создаются всегда первыми, прежде чем что-то еще в C ++?

  3. Где я могу найти эти правила? У меня дома есть несколько книг по С ++, поэтому, если кто-то проявит любезность, либо укажет на книгу (и главу, либо на страницу), либо направит меня на веб-сайт, я был бы очень признателен.

Ниже приведен пример (частичный) код, который я тестировал дома с Visual Studio 2008:

class testclass1
    {
    public:
        testclass1(void);
        ~testclass1(void);

        template<class A> static bool foo(int i)
        {
            std::cout <<"in static foo";    
            return true;
        }
    };


namespace test2
{
    class testclass2
    {
    public:
        testclass2(void);
        ~testclass2(void);
    };

    bool b = testclass1::foo<int>(2);
}

EDIT:

Несколько человек упомянули, что мне нужно вызвать это внутри функции, и это будет работать без проблем.
Я это понимаю; единственная причина, по которой я задал этот вопрос, заключается в том, что я где-то видел этот код (в чьем-то проекте elses) и интересовался, как и почему это работает. Поскольку я никогда раньше не видел, чтобы кто-то делал это.

Кроме того, это используется (в нескольких местах) как способ вызова и создания большого количества таких классов через эти вызовы функций (которые находятся вне). Сначала их вызывают, прежде чем что-либо еще создается.

Ответы [ 5 ]

4 голосов
/ 28 октября 2009

C ++ не является Python. Вы пишете операторы в функции, и выполнение начинается с метода main. Причина, по которой bool b = ... работает, состоит в том, что определяет глобальную переменную b, а вызов функции - это просто выражение инициализации.

Определения могут существовать вне функций, тогда как другие операторы могут существовать только внутри тела функции.

3 голосов
/ 28 октября 2009

Почему я могу вызывать функцию / метод вне класса в пространстве имен, когда я включаю тип возвращаемого значения? (посмотрите на пространство имен test2 :: testclass2)

Ваше объявление b не находится внутри функции, поэтому вы объявляете глобальную переменную. Если бы вы были внутри области действия функции, ваш второй оператор работал бы, но вне функции это не имеет смысла.

Это также отвечает на ваш второй вопрос.

Конечно, вам не разрешат вызывать его таким образом (т.е. не как метод объекта), если это не статическая функция-член.

0 голосов
/ 28 октября 2009

1. Во-первых, полезное исправление: вы сказали «... когда я включаю тип возврата». Я думаю, что вы, возможно, неправильно поняли, что делает <int> часть testclass1::foo<int>(2). Он не обязательно указывает тип возвращаемого значения, он просто предоставляет значение для аргумента шаблона «A».

Вы могли бы выбрать использование A в качестве типа возврата, но у вас есть тип возврата, жестко закодированный как "bool".

По сути, для функции, которую вы написали, вам всегда нужно иметь <> для вызова. C ++ позволяет вам опустить <args> в функции, когда тип может быть выведен из аргументов функции; чтобы заставить это сделать, вы должны использовать аргумент типа A в аргументах вашей функции. Например, если вы объявили функцию таким образом, вы могли бы вызвать ее без <>:

template<class A> static bool foo(A i);

В этом случае это можно было бы назвать "foo (2)", и это вывело бы A из числа два в "int".

С другой стороны, нет никакого способа заставить его выводить что-либо на основе того, для чего вы назначаете функцию. Для вывода аргументов шаблона он смотрит только на аргументы функции, а не на то, что делается с результатом вызова функции. Итак, в:

bool b = testclass1::foo(2);

Нет способа заставить его выводить "bool" из этого, даже если вы сделали A типом возврата.

Так почему же компилятор просто не скажет вам "вам нужно использовать <> в функции"? Даже если вы объявили foo один раз как функцию шаблона, вы могли бы также перегружать его не версией шаблона. Таким образом, компилятор не просто автоматически предполагает, что вы пытаетесь вызвать функцию шаблона, когда вы оставляете <> вне вызова. К сожалению, НЕ предполагая, что вы вызываете template-foo и не видите никакого другого объявления для foo, компилятор возвращается к старому правилу стиля C, где для функции, которая принимает int и возвращает int, на очень старом диалекте C вам не нужно объявлять такого рода, прежде чем использовать его. Таким образом, компилятор предположил, что это именно то, что вы хотели, но затем он заметил, что template-foo и old-crufty-C-foo оба принимают параметр int, и понимает, что он не сможет определить разницу между ними. Итак, он говорит, что вы не можете объявить foo. Вот почему компиляторы C ++ печально известны тем, что выдают плохие сообщения об ошибках - к тому времени, когда об ошибке сообщается, компилятор, возможно, полностью сошел с рельсов и говорит о чем-то, что на три-четыре уровня удалено из вашего реального кода!

2. Да, вы совершенно правы.

3. Я считаю, что ссылки на C ++ и технические документы, которые IBM делает доступными в Интернете, являются наиболее информативными. Вот ссылка на раздел о шаблонах: C ++ Templates

0 голосов
/ 28 октября 2009

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

int main()
{
    testclass1::foo<int>(2);
    return 0;
}
0 голосов
/ 28 октября 2009

Вы можете найти правила, например, Поиск Кенига и шаблон в стандартной документации - удачи в навигации! Вы не упоминаете, какой компилятор вы тестируете, но я не совсем уверен, что он совместим!

Как указывает Mehrdad, вы объявляете и инициализируете глобальную переменную в пространстве имен test2: это не имеет ничего общего со статическими методами.

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