Подтвердить что ты не робот

Статическая функция перегрузки С++ с нестатической функцией

Я хотел бы напечатать две разные вещи в зависимости от того, называется ли функция статически с помощью Foo::print() или из экземпляра Foo foo; foo.print();

EDIT: Вот определение класса, которое определенно не работает, как уже было сказано несколькими людьми.

class Foo {
    string bla;
    Foo() { bla = "nonstatic"; }

    void print() { cout << bla << endl; }
    static void print() { cout << "static" << endl; }
};

Однако есть ли хороший способ достижения этого эффекта? В принципе, я хотел бы сделать:

if(this is a static call)
    do one thing
else
    do another thing

С другой стороны, я знаю, что PHP может проверить, определена ли переменная *this или нет, определить, называется ли эта функция статически. Имеет ли С++ одинаковые возможности?

4b9b3361

Ответ 1

Нет, это запрещено стандартом:

ISO 14882: 2003 С++ Standard 13.1/2 - Перегружаемые объявления

Некоторые объявления функций не могут быть перегружен:

  • Объявления функций, которые отличаются только возвращаемым типом, не могут быть перегружены.
  • Объявления функций-членов с тем же именем и теми же типами параметров не могут быть перегружены если любое из них является объявлением функции static member (9.4).

...

[Пример:

class X {
    static void f();
    void f();                // ill-formed
    void f() const;          // ill-formed
    void f() const volatile; // ill-formed
    void g();
    void g() const;          // OK: no static g
    void g() const volatile; // OK: no static g
};

-end пример]

...

Кроме того, это было бы неоднозначно, так как можно было вызвать статические функции в экземплярах:

ISO 14882: 2003 Стандарт С++ 9.4/2 - Статические элементы

Статический член s класса X может быть упоминается с использованием идентификатора с квалификацией выражение X::s; это не обязательно использовать синтаксис доступа к члену класса (5.2.5) для обозначения a static member. Член static может ссылаться на использование синтаксис доступа к члену класса, в в этом случае object-expressionоценены. [Пример:

class process {
public:
        static void reschedule();
}
process& g();
void f()
{
        process::reschedule(); // OK: no object necessary
        g().reschedule();      // g() is called
}

-end пример]

...

Таким образом, была бы двусмысленность с тем, что у вас есть:

class Foo
{
public:
    string bla;
    Foo() { bla = "nonstatic"; }
    void print() { cout << bla << endl; }
    static void print() { cout << "static" << endl; }
};

int main()
{
    Foo f;
    // Call the static or non-static member function?
    // C++ standard 9.4/2 says that static member
    // functions are callable via this syntax. But
    // since there also a non-static function named
    // "print()", it is ambiguous.
    f.print();
}

Чтобы задать вопрос о том, можно ли проверить, к какому экземпляру вызывается функция-член, существует ключевое слово this. Ключевое слово this указывает на объект, для которого была вызвана функция. Однако ключевое слово this всегда указывает на объект, т.е. Он никогда не будет NULL. Поэтому невозможно проверить, называется ли функция статически или нет à la PHP.

ISO 14882: 2003 С++ Standard 9.3.2/1 - Этот указатель

В теле нестатического (9.3) функция-член, ключевое слово this является выражение не-lvalue, значение которого равно адрес объекта, для которого вызывается функция.

Ответ 2

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

Ответ 3

Ответ - нет, потому что вы не можете перегружать на основе возвращаемого типа.

Конечно, у вас могут быть статические методы в классе, но вы не можете:

static void foo();
void foo();

Поскольку они имеют одну и ту же подпись метода.

РЕДАКТИРОВАТЬ: Я видел ваше замечание о том, почему вы хотели это сделать, и что вы хотели получить доступ к переменным-членам. Вам нужно будет сделать это:

static void print(Foo f);
void print();
....
static void Foo::print(Foo f)
{
    int a = f.a;
    // do something with a
}

(Или создайте геттеры и сеттеры в Foo и т.д., но это общая идея)

Ответ 4

Вы не можете этого сделать, см. В силиконом ответе.

Но вы можете сделать Foo::print() и Foo foo; print(foo); делать разные вещи. (Определите void print(Foo& foo) в том же пространстве имен, что и class Foo, он будет найден ADL).

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