Why does an interface needs to be redeclared? - c++

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.

Related

How does the nested class with override work?

I was wondering how can one explain this mechanism:
class Base{
class Other;
virtual void test() = 0;
};
class Other: Base{
virtual void test() override;
};
void Other::test(){ /*do something*/}
It looks like I have a base class called Base. It contains of a nested class which inherits from the Base. So if I call:
Base obj;
obj.test(); <-- it trigers the test() function from the Other class, doesn't it?
What is the difference between the given example and the following:
class Base{
virtual void test() = 0;
};
class Other: Base{
virtual void test() override;
};
void Other::test(){ /*do something*/}
what would be the benefit of hidding the Other class in the Base class?
class Base{
virtual void test() = 0;
};
Base obj; // #0
#0 is ill-formed as Base is an abstract class, as it has at least one pure abstract member function.
Abstract class
Defines an abstract type which cannot be instantiated, but can be
used as a base class.
A pure virtual function is a virtual function whose declarator has the
following syntax:
declarator virt-specifier(optional) = 0
[...] An abstract class is a class that either defines or inherits
at least one function for which the final overrider is pure virtual.
Dynamic dispatch on polymorphic objects happens when you are dispatching to a virtual function from a base pointer or reference, which (for the specific runtime call) references a derived object.
In the following example:
struct Base {
virtual void test() const = 0;
};
struct A final : public Base {
void test() const override {}; // #1
};
struct B final : public Base {
void test() const override {}; // #2
};
void f(Base const& b) {
b.test(); // #3
}
the call to the virtual member function test() at #3 can dispatch to either A::test() or B::test(), depending on the argument to the function f.
f(A{}); // 'test()' call in 'f' dispatches to #1
f(B{}); // 'test()' call in 'f' dispatches to #2
what would be the benefit of hidding the Other class in the Base class?
In your original example, the Base class declares a nested class (but does not define it) to itself, meaning the Other class declared in Base is not the same as the Other class that derives from it.
Declaring nested classes within a class is a separate topic entirely orthogonal to class inheritance hierarchies
A forward declaration outside of a base class that intends to forward declare a derived class that the base class thinks may derive from it would be an anti-pattern, as the whole point with abstract (interface) classes is to provide a public client API that can be used polymorphically by different derived classes. In other words, a base class should generally never (need to) know about its derived classes (save for the special case of static polymorphism via the curiously recurring template pattern).
The declaration of class Base::Other at line 2 in your first code example, has nothing to do with the declaration of class Other in line 5 of your first code example.
That is, the forward declaration of Base::Other does not match class Other.
There is benefit in having nested classes (for example, some implementations of the pimpl idiom do that), but to define the nested class, you would have to define it with:
class Base::Other {...}; // explicit specification of Base here

create an abstract class from which bass class will be derived c++

I have to make a base class with one derived class in C++. In the end I need to evidence polymorphism between 2 methodes void Read and void Show.
After I did this, I have to create an abstract class Object from which the base class will be derived.This class will contain just pure virtual methods Read and Show.
I don't think I fully understand this. So I make an abstract class Object where I put these 2 methods with "=0" to mke them pure. But this means that I have to edit the base class also, to make it derived from class Object? Like, before:
class Base {
}
after
Class Base : public Object
Can someone make me understand?
You're on the right track. In your Base class, you can mark methods virtual that you intend to be polymorphic. You can set the functions = 0 if they are "pure virtual" and have no implementation in the base class, and are required in any concrete derived class.
class Base
{
public:
virtual void Read() = 0;
virtual void Show() = 0;
};
Then for your derived class you had the syntax backwards. Note that the override keyword indicates that you are overriding a virtual method from the base class. This keyword enforces that the function signature matches the one from a base class.
class Object : public Base
{
public:
void Read() override; // implement this
void Show() override; // implement this
};
The usage could look like the following. Note that you instantiate an Object but carry a pointer to a Base*. Due to polymorphism, the derived implementations are invoked.
int main()
{
Object obj;
Base* p = &obj;
p->Read(); // due to polymorphism will call Object::Read
p->Show(); // due to polymorphism will call Object::Show
}

Declare abstract class in c++

How do i declare abstract class?
For example, I know it's using the keyword virtual like:
class test{
public:
virtual void test()=0;
}
My question is can I abstract test class like this? If not why and how
virtual class test{
}
In most cases, your abstract class contains abstract ("pure virtual" in C++ terms) methods:
class Foo {
public:
virtual ~Foo() = default;
virtual void bar() = 0;
};
That is sufficient to make it an abstract class:
Foo foo; // gcc says: cannot declare variable 'foo' to be of abstract type 'Foo'
Note that you really want to declare the destructor as virtual in your base class, or you risk undefined behavior when destroying your derived object through a base class pointer.
There also might be cases when you have no abstract methods, but still want to mark your class as abstract. There are two ways:
a. Declare your base destructor as pure virtual:
class Foo {
public:
virtual ~Foo() = 0;
virtual void bar() { }
};
Foo::~Foo() = default; // need to define or linker error occurs
b. Declare all your base constructors as protected:
class Foo {
public:
virtual ~Foo() = default;
virtual void bar() { }
protected:
Foo() = default;
};
My question is can I abstract test class like this?
No, you can't. An abstract class by definition is a class that contains at least one pure virtual function.
Your code:
class test
{
virtual void test()=0;
}
creates an abstract class.
it contains one or more pure virtual functions:
virtual void test()=0;//is a pure virtual function/method
An abstract class is a class definition that contains one or more pure virtual functions.
You can't create instances of an abstract class because it is not a complete definition.
Your code:
virtual class test
{
}
is nonsensical, does not rise to the definition of an abstract class because it does not contain one or more pure virtual function, and is an improper use of the 'virtual' keyword...
You may be confused by talk about "Virtual Base Classes" which is a misleading way of referring to the semantic of the "Abstract Class".
purpose for making an abstract class is to inherit it into derived class and there provide a full definition for the pure virtual function/s.
Abstract class could contain many fully defined methods but only one pure virtual method which would make it abstract. The simplistic example is misleading. Abstract classes are common and are often a "fix" for issues arising from the (Barbara) Liskov Substitution Principle.
Dr t

c++ virtual functions in inheriting class

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)

Why can't overridden virtual method see overloaded base classes version without explicit scoping?

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);
}
};