Why using cannot be used to define a virtual function? - c++

I've recently discovered the use of using to import a base class function into the namespace of a derived class (when it is being hidden). I was trying to use it to import a function from a base class as an implementation of the function in a derived class:
class A {
public:
virtual void foo() = 0;
};
class B {
public:
void foo() {
}
};
class C : public A, public B {
public:
using B::foo;
};
int main()
{
C c;
}
This won't compile as A::foo() is a pure virtual function in C. I was hoping that using B::foo; would make an implementation of foo(). Why isn't it so ?

You have two different functions: A::foo() and B::foo(). Although they have the same unqualified name, they are not related. B::foo() does not and cannot override A::foo() because B is not a subclass of A.
C inherits both functions from A and B. You use public inheritance for both base classes, so A::foo() and B::foo() are already visible in C (note that you need qualified name to invoke the functions to avoid ambiguity).
So your using declaration has actually no effect.
A using declaration, when used inside a class, has to do with overloading, but it has nothing to do with overriding. These are very different concepts.
Overloading is about having different functions with the same name but different argument sets.
Overriding is about polymorphism, i.e. having varying implementations of a base-class method in derived classes.
A using declaration introduces a function name from a base class into a derived class, where that name would be hidden by another function with the same name but different arguments. For example:
class X
{
public:
void func() {}
};
class Y : public X
{
public:
void func(int arg) {}
};
Y::func does not override X::func, since its arguments are different. Moreover, it also hides the name func from the base class, so it can be called only via qualified name, e.g.:
X x;
x.func(); // ok
Y y;
y.func(1); // ok, Y::func called
y.func(); // error, base-class name func is hidden by local name
y.X::func(); // ok, qualified name, X::func called
In this case, a using declaration would introduce the name from the base class into the derived class, making func callable without name-qualifying:
class Y : public X
{
public:
using X::func;
void func(int arg) {}
};
// ...
Y y;
y.func(); // ok, X::func called

using in C++ has a different meaning and designates that you would like to be able to access a function/object in another namespace without typing the namespace name explicitly. It has nothing to do with overriding.

Related

Error: request for member '' is ambiguous [duplicate]

The following snippet produces an "ambigious call to foo" error during compilation, and I'd like to know if there is any way around this problem without fully qualifying the call to foo:
#include <iostream>
struct Base1{
void foo(int){
}
};
struct Base2{
void foo(float){
}
};
struct Derived : public Base1, public Base2{
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
So, question is as the title says. Ideas? I mean, the following works flawlessly:
#include <iostream>
struct Base{
void foo(int){
}
};
struct Derived : public Base{
void foo(float){
}
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
Member lookup rules are defined in Section 10.2/2
The following steps define the result of name lookup in a class scope, C. First, every declaration for the name in the class and in each of its base class sub-objects is considered. A member name f in one sub-object B hides a member name f in a sub-object A if A is a base class sub-object of B. Any declarations that are so hidden are eliminated from consideration. Each of these declarations that was introduced by a using-declaration is considered to be from each sub-object of C that is of the type containing the declara-tion designated by the using-declaration. If the resulting set of declarations are not all from sub-objects of the same type, or the set has a nonstatic member and includes members from distinct sub-objects, there is an ambiguity and the program is ill-formed. Otherwise that set is the result of the lookup.
class A {
public:
int f(int);
};
class B {
public:
int f();
};
class C : public A, public B {};
int main()
{
C c;
c.f(); // ambiguous
}
So you can use the using declarations A::f and B::f to resolve that ambiguity
class C : public A, public B {
using A::f;
using B::f;
};
int main()
{
C c;
c.f(); // fine
}
The second code works flawlessly because void foo(float) is inside C's scope. Actually d.foo(5); calls void foo(float) and not the int version.
Name lookup is a separate phase to overload resolution.
Name lookup occurs first. That is the process of deciding which scope the name applies to. In this case we must decide whether d.foo means d.D::foo, or d.B1::foo, or d.B2::foo. The name lookup rules do not take into account function parameters or anything; it is purely about names and scopes.
Only once that decision has been made, do we then perform overload resolution on the different overloads of the function in the scope where the name was found.
In your example, calling d.foo() would find D::foo() if there were such a function. But there is none. So, working backwards up the scopes, it tries the base classes. Now foo could equally look up to B1::foo or B2::foo so it is ambiguous.
For the same reason, you would get ambiguity calling unqualified foo(5); inside a D member function.
The effect of the recommended solution:
struct Derived : public Base1, public Base2{
using Base1::foo;
using Base2::foo;
is that this creates the name D::foo, and makes it identify two functions. The result is that d.foo resolves to d.D::foo, and then overload resolution can happen on these two functions that are identified by D::foo.
Note: In this example D::foo(int) and Base1::foo(int) are two identifiers for the one function; but in general, for the name lookup and overload resolution process, it doesn't make a difference whether they are two separate functions or not.
Will it work for you?
struct Derived : public Base1, public Base2{
using Base2::foo;}

C++11 use variadic subclass when they are template [duplicate]

The following snippet produces an "ambigious call to foo" error during compilation, and I'd like to know if there is any way around this problem without fully qualifying the call to foo:
#include <iostream>
struct Base1{
void foo(int){
}
};
struct Base2{
void foo(float){
}
};
struct Derived : public Base1, public Base2{
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
So, question is as the title says. Ideas? I mean, the following works flawlessly:
#include <iostream>
struct Base{
void foo(int){
}
};
struct Derived : public Base{
void foo(float){
}
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
Member lookup rules are defined in Section 10.2/2
The following steps define the result of name lookup in a class scope, C. First, every declaration for the name in the class and in each of its base class sub-objects is considered. A member name f in one sub-object B hides a member name f in a sub-object A if A is a base class sub-object of B. Any declarations that are so hidden are eliminated from consideration. Each of these declarations that was introduced by a using-declaration is considered to be from each sub-object of C that is of the type containing the declara-tion designated by the using-declaration. If the resulting set of declarations are not all from sub-objects of the same type, or the set has a nonstatic member and includes members from distinct sub-objects, there is an ambiguity and the program is ill-formed. Otherwise that set is the result of the lookup.
class A {
public:
int f(int);
};
class B {
public:
int f();
};
class C : public A, public B {};
int main()
{
C c;
c.f(); // ambiguous
}
So you can use the using declarations A::f and B::f to resolve that ambiguity
class C : public A, public B {
using A::f;
using B::f;
};
int main()
{
C c;
c.f(); // fine
}
The second code works flawlessly because void foo(float) is inside C's scope. Actually d.foo(5); calls void foo(float) and not the int version.
Name lookup is a separate phase to overload resolution.
Name lookup occurs first. That is the process of deciding which scope the name applies to. In this case we must decide whether d.foo means d.D::foo, or d.B1::foo, or d.B2::foo. The name lookup rules do not take into account function parameters or anything; it is purely about names and scopes.
Only once that decision has been made, do we then perform overload resolution on the different overloads of the function in the scope where the name was found.
In your example, calling d.foo() would find D::foo() if there were such a function. But there is none. So, working backwards up the scopes, it tries the base classes. Now foo could equally look up to B1::foo or B2::foo so it is ambiguous.
For the same reason, you would get ambiguity calling unqualified foo(5); inside a D member function.
The effect of the recommended solution:
struct Derived : public Base1, public Base2{
using Base1::foo;
using Base2::foo;
is that this creates the name D::foo, and makes it identify two functions. The result is that d.foo resolves to d.D::foo, and then overload resolution can happen on these two functions that are identified by D::foo.
Note: In this example D::foo(int) and Base1::foo(int) are two identifiers for the one function; but in general, for the name lookup and overload resolution process, it doesn't make a difference whether they are two separate functions or not.
Will it work for you?
struct Derived : public Base1, public Base2{
using Base2::foo;}

why I changed parent virtual function arguments in child hides the father function c++?

I made a class with virtual function f() then in the derived class I rewrote it like the following f(int) why can't I access the base class function throw the child instance ?
class B{
public:
B(){cout<<"B const, ";}
virtual void vf2(){cout<<"b.Vf2, ";}
};
class C:public B{
public:
C(){cout<<"C const, ";}
void vf2(int){cout<<"c.Vf2, ";}
};
int main()
{
C c;
c.vf2();//error should be vf2(2)
}
You have to do using B::vf2 so that the function is considered during name lookup. Otherwise as soon as the compiler finds a function name that matches while traversing the inheritance tree from child -> parent -> grand parent etc etc., the traversal stops.
class C:public B{
public:
using B::vf2;
C(){cout<<"C const, ";}
void vf2(int){cout<<"c.Vf2, ";}
};
You are encountering name hiding. Here is an explanation of why it happens ?
In C++, a derived class hides any base class member of the same name. You can still access the base class member by explicitly qualifying it though:
int main()
{
C c;
c.B::vf2();
}
You were caught by name hiding.
Name hiding creeps up everywhere in C++:
int a = 0
int main(int argc, char* argv[]) {
std::string a;
for (int i = 0; i != argc; ++i) {
a += argc[i]; // okay, refers to std::string a; not int a;
a += " ";
}
}
And it also appears with Base and Derived classes.
The idea behind name hiding is robustness in the face of changes. If this didn't exist, in this particular case, then consider what would happen to:
class Base {
};
class Derived: public Base {
public:
void foo(int i) {
std::cout << i << "\n";
}
};
int main() {
Derived d;
d.foo(1.0);
}
If I were to add a foo overload to Base that were a better match (ie, taking a double directly):
void Base::foo(double i) {
sleep(i);
}
Now, instead of printing 1, this program would sleep for 1 second!
This would be crazy right ? It would mean that anytime you wish to extend a base class, you need to look at all the derived classes and make sure you don't accidentally steal some method calls from them!!
To be able to extend a base class without ruining the derived classes, name hiding comes into play.
The using directive allows you to import the methods you truly need in your derived class and the rest are safely ignored. This is a white-listing approach.
When you overload a member function in a base class with a version in the derived class the base class function is hidden. That is, you need to either explicitly qualify calls to the base class function or you need a using declaration to make the base class function visible via objects of the derived class:
struct base {
void foo();
void bar();
};
struct derived: base {
void foo(int);
using base::foo;
void bar(int);
};
int main() {
derived().foo(); // OK: using declaration was used
derived().bar(); // ERROR: the base class version is hidden
derived().base::bar(); // OK: ... but can be accessed if explicitly requested
}
The reason this is done is that it was considered confusing and/or dangerous when a member function is declared by a derived function but a potenially better match is selected from a base class (obviously, this only really applies to member functions with the same number of arguments). There is also a pitfall when the base class used to not have a certain member function: you don't want you program to suddenly call a different member function just because a member function is being added to the base class.
The main annoyance with hiding member functions from bases is when there is a set of public virtual functions and you only want to override one of them in a derived class. Although just adding the override doesn't change the interface using a pointer or a reference to the base class, the derived class can possibly not used in a natural way. The conventional work-around for this to have public, non-virtual overload which dispatch to protected virtual functions. The virtual member function in the various facets in the C++ standard library are an example of this technique.

What does C++ using mean inside a class?

What does it mean to have a using inside a class definition?
class myClass {
public:
[...]
using anotherClass::method;
};
That declaration unhides a base class member. This is most often used to allow overloads of a member function. Example:
class Base {
public:
void method() const;
};
class Derived : public Base {
public:
void method(int n) const;
// Without the using, you would get compile errors on d.method();
using Base::method;
};
The case I've seen it:
class A
{
void foo(int);
void foo(float);
}
class B : public A
{
void foo(string);
}
B b;
b.foo(12); // won't work!
Because I have implemented a new foo function in B with a different signature it hides the foo functions from A. In order to override this behavior I would do:
class B : public A
{
void foo(string);
using A::foo;
}
Most often, syntax like this is used like so:
class derived : public base {
public:
[...]
using base::method;
};
The using declaration here unhides a member declaration from the parent class. This is sometimes necessary if another member declaration in derived may hide the member from base.
If anotherClass is a base class that contains a member function like
virtual void f();
and you decide to overload the function in the derived class like
virtual void f(int);
it "hides" f() in the base class. Calling f() through a pointer to the derived class for example, would result in an error, since the compiler does not "see" the version of f() taking no arguments from the base class anymore.
By writing
using Base::f;
you can bring the base classes function back into scope, thus enabling overload resolution as you might have expected it to work in the first place.

Why do I have to specify pure virtual functions in the declaration of a derived class in Visual C++?

Given the base class A and the derived class B:
class A {
public:
virtual void f() = 0;
};
class B : public A {
public:
void g();
};
void B::g() {
cout << "Yay!";
}
void B::f() {
cout << "Argh!";
}
I get errors saying that f() is not declared in B while trying do define void B::f(). Do I have to declare f() explicitly in B? I think that if the interface changes I shouldn't have to correct the declarations in every single class deriving from it. Is there no way for B to get all the virtual functions' declarations from A automatically?
EDIT: I found an article that says the inheritance of pure virtual functions is dependent on the compiler:
http://www.objectmentor.com/resources/articles/abcpvf.pdf
I'm using VC++2008, wonder if there's an option for this.
Do I have to declare f() explicitly in B?
Yes, you have to declare in the class' definition all virtual function of any base classes that you want to override in the class. As for why: That's just the way the C++ syntax is.
Note that the virtual keyword can be omitted for the declaration of overriding virtual functions:
class base {
virtual void f();
virtual void g();
};
class derived : public base {
virtual void f(); // overrides base::f()
void g(); // overrides base::g()
};
Note: A class declaration is this: class my_class;, while this class my_class { /* ... */ }; is a class definition. There's a limited number of things you can do with a class that's only been declared, but not defined. In particular, you cannot create instances of it or call member functions.
For more about the differences between declaration and definitions see here.
Ok, for the benefit of the "declaration vs. definition" debate happening in the comments, here is a quote from the C++03 standard, 3.1/2:
A declaration is a definition unless it [...] is a class name declaration
[...].
3.1/3 then gives a few examples. Amongst them:
[Example: [...]
struct S { int a; int b; }; // defines S, S::a, and S::b
[...]
struct S; // declares S
—end example]
To sum it up: The C++ standard considers struct S; to be a declaration and struct S { /*...*/ }; a definition. I consider this a strong backup of my interpretation of "declaration vs. definition" for classes in C++.
Yes, in C++ you have to explicitly clarify your intention to override the behavior of a base class method by declaring (and defining) it in the derived class. If you try to provide a new implementation in derived class without declaring it in class definition it will be a compiler error.
The C++ class declaration defines the content of the class. If you do not declare f() in B, it looks like you do not override it. B::f() can be implemented only if you declare it.
In your current code, you are just inheriting the function f() in class B and you do not redefine base class's member in derived class.
Is there no way for B to get all the
virtual functions' declarations from A
automatically?
If you do not mark the function f in A as pure virtual with =0, the function is automatically also present in any subclass.
class A {
public:
virtual void f(); // not =0!
};
class B : public A {
public:
void g();
};
void A::f() {
cout << "I am A::f!";
}
void B::g() {
cout << "Yay!";
}
Now:
B* b = new B();
b->f(); // calls A::f
By declaring a pure virtual function you are stating that your class is abstract and that you want to require all concrete derived classes to have an implementation of that function. A derived class which does not supply an implementation for the pure virtual function is an extension of the abstract base class and is, itself, an abstract class. Trying to instantiate an abstract class is, of course, an error.
Pure virtual functions allow you to define an interface "contract" that you expect all derived classes to adhere to. A client of that class can expect that any instantiated class with that interface implements the functions in the contract.
Another interesting tidbit... you may supply a body for a pure virtual function but it is still pure and must be overridden in a concrete derived class. The advantage to supplying the body is to provide base behavior while still forcing derived classes to implement the function. The overridden functions can then call the base function Base::F() just like other virtual functions. When the body is not defined, calling Base::F() on a pure virtual functions is an error.