1
class base
{
public:
  static void func()
  {
    cout<<"in base class\n";
  }
};

class derived: public base
{
public:
  void func()
  {
    cout<<"In derived class\n";
  }
};

main() {
  derived d;
  d.func();
}

如果我在基类中创建一个静态函数并在派生类中创建一个具有相同名称的函数,为什么即使该函数是静态的,它也会被重新定义?

4

3 回答 3

2

它不会被重新定义,如果它被重新定义,你会因为一个定义规则而出现编译错误。这里有 2 个函数,一个是成员函数,一个是静态函数。d.func()是成员函数(如.建议的那样)。另一个函数是base::func(),它是静态函数(如::建议的那样)。

于 2014-07-13T13:42:49.870 回答
1

你正在经历“阴影”。成员函数也可以做同样的事情:

#include <iostream>
struct B {
    void func() { std::cout << "in base\n"; }
};

struct D : public B {
    void func() { std::cout << "in derived\n"; }
};

int main() {
    D d;
    d.func();
}

http://ideone.com/kjt2Oa

正如其他人所建议的那样,这被称为“阴影”,一个定义隐藏了另一个。

这里要记住的重要一点是静态函数调用是在编译时解决的。因此,以下将具有您预期的行为,但从技术上讲,这是错误的行为,因为它会阻止您在使用基类指针时调用最顶层的“func”:

void callFunc(base* b) {
    b->func();
}

int main() {
    derived d;
    callFunc(&b);
}

因为在调用站点,b->指向base并且会调用base::func而不是derived::func. 在编译时,编译器只知道 'b' 是base.

大多数人期望并想要动态行为:

#include <iostream>

struct Animal {
    const char* say() { return "???"; }
};

struct Fox : public Animal {
    const char* say() { return "A ring ding ding"; }
};

struct Cat : public Animal {
    const char* say() { return "Meow"; }
};

void whatDoesItSay(const char* name, Animal* animal) {
    std::cout << "The " << name << " says " << animal->say() << ".\n";
}

int main() {
    Cat cat;
    Fox fox;
    whatDoesItSay("cat", &cat);
    whatDoesItSay("fox", &fox);
}

http://ideone.com/9wIzq7

这没有所需的行为:

相反,我们需要在基类中使用关键字“virtual”来表示我们想要完全多态的行为,并且我们可以使用新的 C++11 关键字“override”来确保我们正在这样做:

#include <iostream>

struct Animal {
    virtual const char* say() { return "???"; }
};

struct Fox : public Animal {
    const char* say() override { return "A ring ding ding"; }
};

struct Cat : public Animal {
    const char* say() override { return "Meow"; }
};

void whatDoesItSay(const char* name, Animal* animal) {
    std::cout << "The " << name << " says " << animal->say() << ".\n";
}

int main() {
    Cat cat;
    Fox fox;
    whatDoesItSay("cat", &cat);
    whatDoesItSay("fox", &fox);
}

http://ideone.com/uOtYMv

于 2014-07-13T14:25:31.957 回答
1

它不会被重新定义,否则您将违反单一定义规则。

您看到的是“范围”:
如果在内部范围中定义名称,它会隐藏(隐藏)外部范围中的所有同名定义。

您仍然可以使用显式限定来引用外部范围(基类)中的函数:

base::func

为了将那些从外部范围添加到重载集,请使用using-declaration:

using base::func;

如果这样做,base::func将在使用时调用,derived::func()并在使用derived::func时调用derivedobject.func()

于 2014-07-13T13:43:14.753 回答