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.
Related
Please provide me with a specific answer why function overriding hides the functions that are overloaded in base class.
class Base{
public:
fun(int,int);
fun(B);
};
class Derived:public Base
{
public:
fun();
};
int main()
{
Derived d;
d.fun(1,2); // error
return 0;
}
TTBOMK this doesn't have a real technical reason, it's just that Stroustrup, when creating the language, considered this to be the better default. (In this it's similar to the rule that rvalues do not implicitly bind to non-const references.)
You can easily work around it be explicitly bringing base class versions into the derived class' scope:
class Base {
public:
void fun(int,int);
void fun(Base);
};
class Derived : public Base {
public:
using Base::fun;
void fun();
};
Also refer WHY link as it tells why base overloaded method is hidden in derived class: WHY
I know that when you want to declare a polymorphic function you have to declare the base class function virtual.
class Base
{
public:
virtual void f();
};
My question is are you required to declare the inheriting class function as virtual, even if it's expected that Child behaves as if it were "sealed"?
class Child : public Base
{
public:
void f();
};
No, you don't need to re-declare the function virtual.
A virtual function in a base class will automatically declare all overriding functions as virtual:
struct A
{
void foo(); //not virtual
};
struct B : A
{
virtual void foo(); //virtual
}
struct C : B
{
void foo(); //virtual
}
Declaring f() as virtual in Child helps some one reading the definition of Child. It is useful as documentation.
Once the base class override is marked as virtual all other overrides are implicitly so. While you are not required to mark the function as virtual I tend to do so for documentation purposes.
As of the last part: even if it's expected that Child behaves as if it were "sealed"?, if you want to seal the class, you can actually do it in C++11 (this was not fully implementable in C++03 generically) by creating a seal class like so:
template <typename T>
class seal {
seal() {}
friend T;
};
And then inheriting your sealed class from it (CRTP):
class Child : public Base, virtual seal<Child> {
// ...
};
The trick is that because of the use of virtual inheritance, the most derived type in the hierarchy must call the virtual base constructor (int this case seal<Child>), but that constructor is private in the templated class, and only available to Child through the friend declaration.
In C++ you would have to either create a seal type for every class that you wanted to seal, or else use a generic approach that did not provide a perfect seal (it could be tampered with)
I don't understand why the compiler doesn't like this, here is and example of the problem:
class A
{
public:
virtual void Expand() { }
virtual void Expand(bool flag) { }
};
class B : public A
{
public:
virtual void Expand() {
A::Expand(true);
Expand(true);
}
};
When I try to compile this the A::Expand(true); compiles fine, but the non scoped Expand(true); gets this compiler error:
'B::Expand' : function does not take 1 arguments
You don't need virtual methods for that behaviour. Methods in a derived class hide methods with the same name in the base class. So if you have any function named Expand in your derived class (even if it is an override of a virtual method from the base class), none of the base classes methods with the same name are visible, regardless of their signature.
You can make the base classes methods visible with using. For that you would add using A::Expand; to the definition of B:
class B : public A
{
public:
using A::Expand;
virtual void Expand() { Expand(true); }
};
That's because besides overriding the base Expand(), you're also hiding the base Expand(bool).
When you introduce a member function in a derived class with the same name as a method from the base class, all base class methods with that name are hidden in the derived class.
You can fix this by either qualifying (as you have) or with the using directive:
class B : public A
{
public:
using A::Expand;
virtual void Expand() {
A::Expand(true);
Expand(true);
}
};
Is there a way you can invoke a member function of a base class upon a class derived from it?
Class Bass{
public:
void func();
};
Class Derived: public Base{
public:
void func();
};
I have a practice midterm, and I suspect no, because how would the Base class know about the Derived, but I am not sure.
Is there a way you can invoke a member function of a base class upon a class derived from it?
Not sure exactly what you mean by this, but given your Base and Derived classes you can do the following. Just make sure you use a reference or pointer, not pass-by-value because of the slicing problem.
Call Base::func() from within Derived::func():
void Derived::func()
{
Base::func();
}
Call Base::func() explicitly on a Derived object:
Derived d;
d.Base::func();
I [...] am wondering if you could do something like Base::func(Derived d)
As others have pointed out, you can do this using a forward declaration:
// Tell the compiler "Derived" is a class name.
class Derived;
class Base
{
// Can use the class name since it has been declared.
void func(Derived& derived);
};
// Define the class named "Derived".
class Derived : public Base
{
// ...
};
// Use the derived class.
void Base::func(Derived& derived)
{
// For this bit to work, the definition of `Derived` must
// be visible at this point (like putting the class above
// or including your "Derived.h" from "Base.cpp").
derived.some_derived_method();
}
However, you won't be able to define the Base::func(Derived&) directly in the class definition since you need to finished defining Base and to define Derived first.
if I understand correctly, you need to call base function with derived parameter?
You can do it only using forward declaration and passing derived object by pointer or ref.
class Derived;
class Base{
public:
void func(Derived&);
};
You should be able to do something like this:
class Derived;
class Base {
public:
void func();
void func(Derived);
};
class Derived : public Base {
public:
void func();
};
void
Base::func(Derived D) {
}
It is okay to use incomplete types in the Base's member function declarations, but you must provide the complete type before their definition.
You can use forward declaration of Derived class:
class Derived;
First of all, do you mean methods on an object, or static class methods?
Secondly, the answer is: it depends what the object you're invoking the method call on is. This is the nature of polymorphism: if your object is of type 'Derived', then even if it has been cast to a 'Base' the method call will still invoke the Derived version of func.
Is that what you were asking?
Given this code:
class base {
public:
string foo() const; // Want this to be visible in 'derived' class.
}
class derived : public base {
public:
virtual int foo(int) const; // Causes base class foo() to be hidden.
}
How can I make base::foo() visible to derived without replicating it with a dummy method overloading that calls the base class? Does using do the trick, if so, where does it go, is it like this?
class derived : public base {
public:
virtual int foo(int) const;
using base::foo;
}
Sorry for the short answer, but yes. It's exactly like this and does what you want:
class derived : public base {
public:
virtual int foo(int) const;
using base::foo;
};
Also note that you can access the base even without using:
derived x;
string str = x.base::foo(); // works without using
The using directive will make selected methods from base visible to the scope of derived. But from a design point of view this is not desirable, since you're hiding names to the scope of derived while using a public interface. (Doing this with a private interface makes more sense)