Say we have this:
class A
{
public:
virtual void foo() = 0;
};
class B: public A
{
public:
virtual void foo() = 0;
};
The compiler throws no error, I guess its because B is also an abstract class and as such it does not have to implement foo from A.
But what does such a construct mean?
1) Does foo from B hide foo from A?
2) The first class which inherits from B and is not an abstract class, does it have to provide two implementations like:
class C: public B
{
public:
virtual void A::foo() {};
virtual void B::foo() {};
};
The compiler only complains if the implementation of B::foo() is missing, but it does not complain about a missing A::foo().
All in all: is this a way to hide pure virtual methods?
When you first declare:
class A
{
public:
virtual void foo() = 0;
};
you are declaring the method foo public, virtual and pure. When a class contains at least a pure method it's called abstract. What does it mean? It means that the class cannot be instantiated because it needs the pure methods implementations.
You can obviously inherit from an abstract class (I'd say that you are forced to do that, otherwise what would be the need of an abstract class you are not using, except for providing an interface to inherit from?) and you can also inherit from an abstract class and not implement some or all of the pure methods of the parent class; in this case the child class is abstract as well, which is the case of your class B:
class B: public A
{
public:
virtual void foo() = 0;
};
In B you could easily omit the virtual void foo() = 0; declaration because the definition is already inherited from the base class. In this case class B is an abstract class and therefore cannot be instantiated, just like A.
To answer your questions more directly:
Does foo from B hide foo from A?
No, it does not. They both are declaring a pure method (which is in fact the same method), therefore there's nothing to really hide.
The first class which inherits from B and is not an abstract class, does it have to provide two implementations like the one provided?
No, of course not. As stated above, they are the same method, therefore if class C have to provide an implementation for foo it should just implement foo:
class C: public B
{
public:
virtual void foo() {};
};
0) The compiler throws no error ...
It will throw an error when you try to instantiate an object from A or B which they're abstract. Not when you're inheriting and declaring them.
1) Does foo from B hide foo from A?
No. It overtides A::foo not hides it.
2) The first class which inherits from B and is not an abstract class,
does it have to provide two implementations ...
No. Just override foo and make one implementation for it.
class C : public B
{
public:
virtual void foo()
{
std::cout << "ABCD" << std::endl;
}
};
int main()
{
C c;
A *a = &c;
a->foo(); // Prints ABCD string and proofs B::foo doesn't hide A::foo
}
I compiled your code with gcc 4.5.3, it gave the following error messages:
error: cannot define member function ‘A::foo’ within ‘C’
error: cannot define member function 'B::foo' within 'C'
In you example, both class A and B are abstract classes since foo is pure virtual. They only define that derived class of B should implement the behavior of foo since there is no default behavior to use (if the derived class is not abstract anymore).
Question 1:Does foo from B hide foo from A?
Since foo in B and A has exactly the same name, same signature and foo is virtual in base class, so it is not hiding, it is overriding. FYI: A derived class's function overrides a base class function if the signature is the same and it's declared virtual in the base class. If you call it
through a pointer or a reference to the base class, the function in the
derived class is called. It "overrides" the one in the base class.
Hiding only comes into play if you call a non-virtual function through a
pointer or reference or directly with an object of the derived class. A
derived class' function hides all base class functions with the same name.
Question 2: The first class which inherits from B and is not an abstract class, does it have to provide two implementations
No. You can do the following:
class C: public B
{
public:
virtual void foo()
{
cout << "foo defined in c" <<endl;
}
};
Related
Consider following code:
class A {
public:
virtual void f() const = 0;
void callf() const { f(); }
};
class B : public A {
virtual void f() const { }
};
int main()
{
B x;
x.callf();
return 0;
}
Class B derives from the abstract base class A, but "hides" the implemented method f() as private member.
Still, the inherited member callf() is able to call f(), which was public in the base class.
The code compiles with no warning on g++ 10.1.0 and clang++ 11.1.0.
Is this a legal code, i.e., does the inherited callf() correctly see the private member f()?
Alternatively, would it be possible for the derived class B to implement the purely virtual methods of the base class, such that they can only be called by B (and friends)?
Is this a legal code, i.e., does the inherited callf() correctly see the private member f()?
Yes, it is legal code. From the compiler's point-of-view, the callf function is referencing the f function of its own class; the fact that that is a virtual function does not affect the scope (or accessibility) – only the implementation, which will be in the form of a call to a v-table entry. That v-table entry will be correctly interpreted at run time, when it is called via the derived class.
When I have something like this, and when I have a* mya=new c(); and I call a->displayStuff it calls Class a method, and when virtual is in Class a instead of Class b, it calls Class b method.
Since Class c has no implementation of this method, what is the rule applied here?
class a
{
public:
void displayStuff() {}
//other methods
};
class b:public a
{
public:
virtual void displayStuff() {}
//other methods
};
class c:public b
{
//other methods
};
In the first your case class A has no virtual function. So its non-virtual function displayStuff will be called. in the second case when you added function specifier virtual to the function in class A the corresponding function inclass B redefines this function. So in the second case the function of class B is called because the table of virtual function pointers contains a pointer to the function defined in class B.
Since Class c has no implementation of this method, what is the rule
applied here?
The rule of inheritance applies. Based on the visibility of the inherited member and the inheritance type, the members visible in Class B would be visible in Class C. In this case, as you are inheriting publicly, all public members would be visible publicly. So, the public virtual member function in Class B would be visible as a public virtual function in Class C.
Exactly, but when to use what and why when I have multiple levels of
inheritance?
Its a design decision. Remember, a non virtual member function is bound at compile time, so any Function Call via a base pointer cannot be resolved until you intend to call the function.
Consider the scenario
Base
public: foo
/ \
/ \
/ \
/ \
/ \
Derived1 Derived2
public: foo public: foo
Base *p;
std::cin>>cond;
if (cond)
p = new Derived1();
else
p = new Derived1();
p->foo();
In the above code, the decision to call foo() (Derived1::foo or Derived2::foo), depends on some external condition which cannot be determined at runtime. The only way to make this possible is create a vTable which can only be forced to be created if we make at-least one function in a class virtual (Note any virtual function in the base class continues to remain virtual in the derived class).
I have an abstract base class and want to implement a function in the derived class. Why do I have to declare the function in the derived class again?
class base {
public:
virtual int foo(int) const = 0;
};
class derived : public base {
public:
int foo(int) const; // Why is this required?
};
int derived::foo(int val) const { return 2*val; }
Consider that the derived-class definition might be in a header, whereas its implementation may be in a source file. The header typically gets included in multiple locations ("translation units"), each of which will be compiled independently. If you didn't declare the override, then the compiler wouldn't know about it in any of those other translation units.
The intention of making a function pure virtual in Base class is that the derived class must override it and provide its own implementation.
Note that presence of an pure virtual function in the class makes that class an Abstract class. In simple terms the class acts as an interface for creating more concrete classes.One cannot create objects of an Abstract class.
If you do not override the pure virtual function in derived class then the derived class contains the inherited Base class pure virtual function only and it itself acts as an Abstract class too.Once your derived class is abstract it cannot be instantiated.
So in order that your derived class be instantiated it needs to override and hence declare the pure virtual function.
You might think the compiler can deduce that you're going to have to provide an implementation of derived::foo(), but derived could also be an abstract class (and in fact that's what you'll get if you dont declare foo() in derived)
It is to override the abstraction of the base class.
If you do not re-declare it, then your derived class is also an abstract class. If you do then you now have a non-abstract type of the base.
Because the hierarchy could have more layers.
struct Base {
virtual void foo() const = 0;
virtual void bar() const = 0;
};
struct SuperBase: Base {
virtual void bar() const override;
};
struct Concrete: SuperBase {
virtual void foo() const override;
};
Here, SuperBase does not provide an implementation for foo, this needs be indicated somehow.
While you can't instantiate a class with pure virtual functions, you can still create a class like this:
class base {
public:
virtual int foo(int) const = 0;
};
class derived : public base {
public:
};
class very_derived : public derived {
public:
virtual int foo(int) const { return 2; }
};
The derived class is still an abstract class, it can't be instantiated since it doesn't override foo. You need to declare a non-pure virtual version of foo before you can instantiate the class, even if you don't define foo right away.
Say we have a class inheriting from two base classes (multiple inheritance). Base class A is abstract, declaring a pure virtual function foo, the other base class B declares and implements a function foo of the very same signature.
struct A
{
virtual void foo(int i) = 0;
};
struct B
{
virtual void foo(int i) {}
};
struct C : public A, public B {};
I want to use the implementation of foo from base class B in my derived class C. However, if I do not implement the function foo a second time in my derived class C, I cannot instantiate any object of it (it remains abstract). Virtual inheritance does not help here as expected (class A and class B have no common base class).
I wonder if there is a way to "import" the implementation of foo from class B into class C in order not to have to repeat the same code.
Above example is of course contrived. The reason I want implement foo in class B is that I want to derive class D : public B and use class Bs implementation of foo. I know that inheritance is not (primarily) intended for code reuse, but I'd still like to use it in that way.
In java, your sample code works. In C++ it doesn't. A subtle difference between those languages.
Your best option in C++ is to define C::foo() by forwarding to B::foo():
struct C : public A, public B
{
virtual void foo(int i) { B::foo(i); }
};
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.