42

我想打印两个不同的东西,具体取决于一个函数是用实例静态调用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

5 回答 5

63

不,是标准直接禁止的:

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 – 静态成员

可以使用qualified-id 表达式来引用s类的静态成员;不必使用类成员访问语法 (5.2.5) 来引用. 可以使用类 成员访问语法来引用成员,在这种情况下会评估。[例子:XX::sstatic memberstaticobject-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是一个非左值表达式,其值是调用该函数的对象的地址。

于 2011-03-19T23:40:43.570 回答
2

这是绝对不允许的。我没有看到任何干净的方法来实现这一目标。您想以这种方式解决的问题到底是什么?

于 2011-03-19T23:41:09.097 回答
1

答案是否定的,因为您不能基于返回类型重载。

你当然可以在一个类中拥有静态方法,但你不能拥有:

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 等中创建 getter 和 setter,但这是一般的想法)

于 2011-03-19T23:43:53.600 回答
1

您不能完全做到这一点,请参阅In silico's answer

但是你可以制作Foo::print()Foo foo; print(foo);做不同的事情。(void print(Foo& foo)在与 相同的命名空间中定义class Foo,它将被 ADL 找到)。

无论如何,这不是一个好主意。您有两个名称非常相似的函数,它们做的事情完全不同,这违反了良好的设计原则。

于 2011-03-19T23:49:56.293 回答
0

1)如果函数的返回类型不同,方法重载是不可能的。

2)如果我们在同一个类下定义的函数中传递相同的参数,那么它就不能重载。

于 2021-09-17T11:09:32.803 回答