简体   繁体   中英

Using declaration and multiple inheritance

We know that a 'using declaration' for a namespace's member name in a scope where another entity is defined there with the same name, causes a compile time error: "symbol x is already defined".

The error is detected at the point the 'using declaration' appears not at use point like a 'using directive'.

A using declaration in a class scope allows only exposing a base class member name.

Here is an example:

#include <iostream>
using namespace std;

struct Foo{
    Foo(int x) : x_(x){}
    int x_ = 0;
};

struct Bar{
    Bar(int y) : y_(y){}
    int y_ = 0;
};

struct FooBar : Foo, Bar{
    using Foo::Foo; // inheriting Foo's ctors
    using Bar::Bar; // inheriting Bar's ctors

    int x_ = 10;
//    using Foo::x_; // error detected here
};

int main(){
    FooBar fb(5); // error detected here

}

As you can see above the using declaration for Foo::x_ causes a compile-time error at the point the using appears and it is OK.

But the using declaration for base classes Foo and Bar constructors don't issue an error until the usage in main?!!

  • Normally FooBar inherits Foo(int); so when using Bar::Bar; appears normally the compiler complains but the code works fine until I try to use that constructor. FooBar(int) .

After inheriting all the constructors, the compiler defines a derived class ctor and make it call its base class one passing in its parameters to it so it is as if we wrote:

struct FooBar : Foo, Bar{
        FooBar(int x) : Foo(x){}
        FooBar(int x) : Bar(x){}
//...
};

So why the compiler allows such bug? and wait until the use of that ctor to flag ambiguity??

  • It looks to me that a using declaration in such case undergoes the same thing like a using directive.

It is a general (though not universal) principle of C++ that a prefix of a program is valid if and only if there is some valid completion of it that uses the declarations in the prefix. This is why it's not an error to declare an unused variable: it could be used, and it's “too late” to reject it later if it's not. Here, that principle is generalized a bit to say that, because overload resolution can usually distinguish between functions from different namespaces or base classes, there is no check for conflict at all.

Not so for variables , since you can't possibly use the ambiguous combination. Also not so if one of the conflicting functions declarations is a direct member and a sibling of the using-declaration : in that case, you can't possibly use the function you declared, so you are presumed not to have meant it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM