Статическая функция перегрузки C ++ с нестатической функцией - PullRequest
33 голосов
/ 20 марта 2011

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

РЕДАКТИРОВАТЬ: вот определение класса, которое определенно не работаеткак уже отвечали несколько человек.

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 или нет, чтобы определить, вызывается ли функция статически.Имеет ли C ++ такую ​​же возможность?

Ответы [ 4 ]

55 голосов
/ 20 марта 2011

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

ISO 14882: 2003 C ++ Стандарт 13.1 / 2 - Объявления о перегрузке

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

  • Объявления функций, отличающиеся только типом возвращаемого значения, не могут быть перегружены.
  • Объявления функций-членов с одинаковыми именами и одинаковыми типами параметров не могут быть перегружены если какой-либо из них является static объявлением функции-члена (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
};

- конец примера]

...

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

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

Статический член s класса X может быть упоминается с использованием qualid-id выражение X::s; это не обязательно использовать синтаксис доступа члена класса (5.2.5) для обозначения 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
}

- конец примера]

...

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

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's also a non-static function named
    // "print()", it is ambiguous.
    f.print();
}

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

ISO 14882: 2003 C ++ Стандарт 9.3.2 / 1 - Указатель this

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

2 голосов
/ 20 марта 2011

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

1 голос
/ 20 марта 2011

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

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

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

1 голос
/ 20 марта 2011

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

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

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 и т. Д., Но это общая идея)

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