1

Consider the following code snippet:

#include <iostream>

using namespace std;

struct Element {
    void SetVisible(bool) { cout << "Called SetVisible on Element" << endl; }
};

struct ElementQuery {
    ElementQuery(Element * e) : element(e) { }
    Element * Get() const { return element; }
    Element * element;
};

namespace A {

static void SetVisible(ElementQuery const& element, bool show) {
    cout << "Called SetVisible on ElementQuery" << endl;
    SetVisible(element.Get(), show);
}

static void SetVisible(Element * element, bool show) {
    element->SetVisible(show);
}

};

int main() {
    Element * e = new Element();
    ElementQuery q(e);
    A::SetVisible(q, true);
    delete e;
    return 0;
}

When run, program fails because of infinite recursion in call SetVisible(element.GetFirst(), show). As I presume that is so because of function SetVisible(Element * element, bool show) is not declared yet at the time of call though it fits overload resolution better.

But when I change namespace A to struct A, recompile and run, everything works fine. Program prints two lines to cout and ends gracefully.

My question is: why does the second call "sees" second declaration of SetVisible and what are the differences between such declarations?

4

2 回答 2

1

It's because the namespace is processed in order and there exists a conversion between Element and ElementQuery (because your constructor is not explicit).

Here is the corrected code

#include <iostream>

using namespace std;

struct Element {
    void SetVisible(bool) { cout << "Called SetVisible on Element" << endl; }
};

struct ElementQuery {
    explicit ElementQuery(Element * e) : element(e) { }
    Element * Get() const { return element; }
    Element * element;
};

namespace A {

static void SetVisible(Element * element, bool show) {
    cout << "Called A::SetVisible on Element" << endl;
    element->SetVisible(show);}

static void SetVisible(ElementQuery const& element, bool show) {
    cout << "Called A::SetVisible on ElementQuery" << endl;
    SetVisible(element.Get(), show);
}

};

int main() {
    Element * e = new Element();
    ElementQuery q(e);
    A::SetVisible(q, true);
    delete e;
    return 0;
}
于 2012-06-28T09:46:27.357 回答
0

It seems this code should not be compiled at all. Because this call: SetVisible(element.Get(), show); The $void SetVisible(Element * element, bool show) is not visible at moment call. You need to move this function before $void SetVisible(ElementQuery const& element, bool show).

于 2012-06-28T09:44:27.373 回答