I have an abstract class with a pure virtual function f() and i want to create a class inherited from that class, and also override function f(). I seperated the header file and the cpp file.
I declared the function f(int) in the header file and the definition is in the cpp file. However, the compiler says the derived class is still abstract.
How can i fix it?
The functions f() and f(int) do not have the same signature, so the second would not provide an implementation for the first. The signatures of the PVF and the implementation must match exactly.
Are you declaring f(int) in your base class as pure virtual or f()?
Pure virtual functions can have definitions inside their base class. A pure virtual function simply says that the derived type must also specify their own implementations of the function f(int).
class Base
{
public:
virtual void f(int) = 0;
}
Base::f(int)
{
//some code
}
class Derived : public Base
{
public:
virtual void f(int)
{//Implementation is needed in Derived since f(int) is pure virtual
}
}
What about using C++ templates?
template<typename T>
class Basic{
public:
void f(T);
};
template<typename T>
Basic<T>::f(T t){
//Do something generic here
}
You can use template specialization if your function f needs to do something else when it's parameter is a specific type. I'll use string in this example.
template<>
class Basic<string>{
public:
void f(string);
};
template<>
Basic<string>::f(string t){
//Do your special thing with a string
}
Hope this helps!
Related
Let's imagine simple typelist:
template<typename...Types>
struct TypeList
{}
I would like to use such typelist to generate N virtual functions in single interface for each type, and generate N implementations of that also in single impl type, which can decay to interface.
My attempt:
template<typename Type>
struct Itf_SingleType
{
virtual void process(const Type&) = 0;
};
template<typename...>
struct Itf;
template<typename...Types>
struct Itf<TypeList<Types...>> : Itf_SingleType<Types>...
{
using Itf_SingleType<Types>::process...;
virtual ~Itf() = default;
};
At this point I have N virtual functions in interface. But I have problem with attaching implementations:
template<typename Type>
struct Impl_SingleType
{
void process(const Type&)
{
//can be anything at this point, so let it be this:
puts(__PRETTY_FUNCTION__);
}
};
template<typename...>
struct Impl;
template<typename...Types>
struct Impl<TypeList<Types...>> : Itf<TypeList<Types...>>, Impl_SingleType<Types>...
{
using Impl_SingleType<Types>::process...;
};
Wandbox with example: https://wandbox.org/permlink/s0n1DX7t7we8d6mM
However I still get two errors:
Dunno why it cannot choose between process(const int&) and process(const std::string&) with process(7). fixed by adding using Itf_SingleType<Types>::process...; to Itf
Dunno why it still think it's not overloaded despite using declaration inside Impl
We can assume C++17 support.
Itf_SingleType::process doesn't override Itf_SingleType::process because the two classes are unrelated. A class that inherits from both will simply have two different unrelated functions named process with the same signature. Here is how you can fix that:
template<typename...Types>
struct Itf<TypeList<Types...>> : virtual Itf_SingleType<Types>... // virtual!
...
template<typename Type>
struct Impl_SingleType : virtual Itf_SingleType<Type> // <- virtual!
{
void process(const Type&) override // now we override
{
}
};
If some member function vf is declared as virtual in a class Base, and some class Derived, which is derived, directly or indirectly, from Base, has a declaration for member function with the same
name
parameter type list (but not the return type)
cv-qualifiers
ref-qualifiers
Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration) and overrides Base::vf (whether or not the word override is used in its declaration).
A virtual member function vf of a base class Base is the final overrider unless the derived class declares or inherits (through multiple inheritance) another function that overrides vf.
An abstract class is a class that either defines or inherits at least one function for which the final overrider is pure virtual.
Factly, Impl is an abstract class because its final overriders of process are still pure virtual. (process I mentioned means any instantiations of process<T>.)
why? because Impl_SingleType doesn't inherit Itf_SingleType, so Impl_SingleType::process doesn't override the pure virtual function declaration Itf_SingleType::process. so neither Impl::process (it doesn't exist) nor Impl_SingleType::process can override Itf_SingleType::process. the final overrider is actually Itf_SingleType::process itself!
so to let this code valid, you should let Impl_SingleType inherit Itf_SingleType.
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.
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 have two classes as follows in a header file
template<size_t N>
class Parent{
protected:
char array[N];
size_t i;
public:
virtual void operator()(int i);
};
template<size_t N>
void Parent<N>::operator()(int i){
this->i = i;
}
class Child: public Parent<16>{
public:
virtual void operator()();
};
Child has operator()() defined elsewhere in a cpp file. Whenever I include this header file from another cpp file I can access operator()() but operator()(int) is not even defined. Why is this? I thought since I inherit from a specific instance of Parent, all the methods of it should be instanced as well and available.
Apart from the errors in your code, this is an example of hiding: Your derived class declares a function of the same name but with different signature as a base class. Thus the base function is hidden:
class A { virtual void foo(); };
class B : public A { virtual void foo(int); /* hides A::foo() ! */ };
Inheritance only affects functions that have the same signature (with some mild exceptions).
Your base class function is declared as void Parent<N>::operator()(int), while in your derived class you declare void Child::operator()().
In C++11 you can explicitly say virtual void foo(int) override to trigger a compiler error if the function isn't overriding anything.
If you intentionally want to define a new function with the same name as an existing one but with different signature, and not overriding the base function, then you can make the base function visible with a using directive:
class C : public A
{
using A::foo();
void foo(int);
}; // now have both C::foo(int) and C::foo()
Because the Parent's operator() hides the Child's operator() (they have different signatures). How come you are not getting warnings when you compile your code?
This is how it should be :
class Child: public Parent<16>{
public:
using Parent<16>::operator();
virtual void operator()();
};
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.