【问题标题】:C++ Overload Static Function with Non-Static FunctionC++ 用非静态函数重载静态函数
【发布时间】:2011-07-18 22:50:22
【问题描述】:

我想打印两个不同的东西,具体取决于函数是使用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++ 有同样的能力吗?

【问题讨论】:

  • print() 的两个版本具有相同的签名。而且我认为它们不能以这种方式超载。

标签: c++ static overloading non-static


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    不,是标准直接禁止的:

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

    X 类的静态成员 s 可能是 提到使用 qualified-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 是 非左值表达式,其值为 对象的地址 函数被调用。

    【讨论】:

    • 感谢您给出非常明确的答案,但我在问(很抱歉,我为此道歉)静态函数的行为是否可以根据它是静态调用还是从班级。请参阅我的问题的后半部分。
    • @Lex Fridman:我不认为你问得不好。您问“C++ 是否具有相同的功能?”我回答说你不能基于 C++ 标准(它定义语言)。
    • 我对这个问题的措辞感到越来越糟,尤其是标题。其实有两个问题。首先,如果你可以用非静态重载静态。这就是你回答得很好。第二个问题是您是否可以确定是否存在与调用静态函数相关联的类的实例。正如您所说,您可以使用这样的静态函数:Foo foo; foo.print(); 我可以从对print(); 的调用中访问foo 实例吗?
    • @Lex Fridman:啊,好的。你已经为我澄清了,所以不要担心你的措辞。我会回答那部分。
    【解决方案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 等中创建 getter 和 setter,但这是大体思路)

    【讨论】:

    • 但如果他这样做了,下一个维护者将有一个重大的 WTF 时刻,试图理解为什么有人更喜欢 Foo::print(f) 而不是 f.print()
    【解决方案4】:

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

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

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

    【讨论】:

    • 我知道这似乎是糟糕的设计,因为我没有准确解释我要解决的问题。这实际上对我正在做的事情有意义。但是,在 C++ 的上下文中,这可能是一种不好的做法。我知道用 PHP 这样的解释型语言来做是件好事。
    • @Lex:这两个函数必须做不同的事情,所以其中一个肯定可以有不同的名称。也许Foo::PrintLiveFooCount();Foo foo; foo.print();
    【解决方案5】:

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

    【讨论】:

    • 解释起来有点复杂,但我有一些非静态变量,我希望从类的实例调用静态函数时可以访问这些变量。我可以将函数命名为其他名称并使其成为非静态的,但我认为它会提供一个很好的一致 API,只有一个函数可供用户使用。对不起,如果这没有意义。
    • @Lex - 您似乎误解了“静态”的含义。您不能使用静态方法访问非静态变量;你不是在处理类的实例化。这样做的唯一方法是将类的实例化传递给静态方法。
    • 我认识 Brian,但您可以“非静态地”调用静态成员,所以不要使用 Foo::print();,而是使用 Foo foo; foo.print();
    • 你不是在“非静态地”调用它......它仍然在类中调用相同的静态函数,并且与你碰巧在那里的类的实例无关。这与Foo::print(); 没有什么不同,请参阅:stackoverflow.com/questions/325555/… - 我相信这是您困惑的根源。
    • 啊,好吧,那么foo 的实例在这种情况下没有意义,不能从print() 中访问。感谢您的澄清,布赖恩
    猜你喜欢
    • 2012-06-28
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    相关资源
    最近更新 更多