Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
697 views
in Technique[技术] by (71.8m points)

Why can't redefine type names in class in C++?

According to the book C++ Primer section, 7.4.1 Type Names Are Special:

Ordinarily, an inner scope can redefine a name from an outer scope even if that name has already been used in the inner scope. However, in a class, if a member uses a name from an outer scope and that name is a type, then the class may not subsequently redefine that name.

Accordingly, for example:

typedef double Money;
class Account {
    public:
        Money balance() { return bal; }
    private:
        typedef double Money;
        Money bal;
};

int main() {
    typedef double Money;
    Money asset;
    typedef double Money;
    return 0;
}

When you compile the example above, it will complain:

a.cc:6:24: error: declaration of ‘typedef double Account::Money’ [-fpermissive]
         typedef double Money;
                        ^
a.cc:1:16: error: changes meaning of ‘Money’ from ‘typedef double Money’ [-fpermissive]
 typedef double Money;

So why can not we redefine type names in class, but can we in the inner scope?


My compiler version is g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609.
And there is also a note in that section:

Although it is an error to redefine a type name, compilers are not required to diagnose this error. Some compilers will quietly accept such code, even though the program is in error.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is not unique to types. [basic.class.scope]/2:

A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

The reason is that name lookup in class scope is a little special. Consider:

using Foo = int;

struct X {
    Foo a;    // ::Foo, i.e., int
    void meow() { 
        Foo b = a; // X::Foo; error: no conversion from int to char*
    }
    using Foo = char*;
};

Name lookup in member function bodies considers all class members, whether declared before or after the member function (otherwise, a member function defined in a class definition wouldn't be able to use a data member declared later in the class). The result is that you get two Foos with different meanings, even though they both lexically precede the class member Foo's declaration. This can easily lead to extremely confusing and brittle code, and so the standard bans it.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...