Consider:
struct device{
virtual void switchon() = 0 {}
};
int main()
{
}
I wrote code similar to following and it gave an error:
pure-specifier on function-definition
compilation terminated due to
-Wfatal-errors.
When I asked him, he showed me the following quote from the standard:
A virtual function declared in a class
shall be defined, or declared pure
(10.4) in that class, or both; but no
diagnostic is required (3.2).
I can't seem to understand what it means and I think this somehow is not relevant.
PS: If this is not the relevant quote, please guide me to the proper one so that I can have a better counterargument.
A pure virtual function may have a definition (out of class definition). That is completely optional. But what you are trying to do is plain wrong because
C++03 [Section 10.4/2] says:
[Note: a function declaration cannot provide both a pure-specifier and a definition —end note] [Example:
struct C {
virtual void f() = 0 { }; // Ill-formed
}
However you are free to write
struct device{
virtual void switchon() = 0;
};
void device::switchon() { } // Definition {optional}
int main()
{
}
You can have a "pure" virtual function, i.e. base class has no implementation of the function
virtual void switchon() = 0;
and optionally provide an implementation which derived classes must override.
void base_class::switchon() {}
OR
you can have a "non-pure" virtual function and provide a default or empty implementation
virtual void switchon() {}
Related
Virtual functions cannot be constexpr however, when a function is implicitly virtual through inheritance, the compilers I have tried don't complain about it.
Here is a sample code:
class A
{
virtual void doSomething() {}
};
class B : public A
{
constexpr void doSomething() override {} // implicitly virtual constexpr
// but no compilation error
};
class C : public A
{
virtual constexpr void doSomething() override {} // explicitly virtual constexpr
// compilation error
};
I tried it with gcc 7.2.0 and clang 5.0.0.
Are those compilers not compliant to the standard in this regard, or are implicitly virtual constexpr functions allowed ?
The compilers have a bug. Note that this has been fixed in clang 3.5 already, not sure why you don't get an error, because I do.
The standard is pretty explicit about this in [dcl.constexpr]p3:
The definition of a constexpr function shall satisfy the following requirements:
it shall not be virtual;
[...]
It does't matter whether doSomething is implicitly virtual or not. In both cases, it is considered to be virtual, and so it violates the point above.
override and final specifier has been introduced in C++11.The below program uses these specifier as follows:
#include<iostream>
template<typename T>
void display(const T& val) { std::cout<<val<<"\n"; }
class Shape {
public:
virtual ~Shape()= default;
virtual void Draw() { display("Shape::Draw()");}
virtual void DisplayName() { display("Shape");}
};
class Circle : public Shape {
public:
virtual ~Circle() = default;
virtual void Draw() override final { display("Circle::Draw()");}
virtual void DisplayName() override { display("Cicle");}
};
int main()
{
}
In the above sample program Circle::Draw() has been defined as override final specifier. This compiles successfully however if the same method is defined as final override, then it throws an compile time error.
Wanted to understand the use cases of override and final specifier for the same method for a class?. When we should use it in our program?
In my opinion it is a compiler bug. At least at www.ideone com the code is compiled successfully.
Acoording to the C++ Standard (10.3 Virtual functions)
4 If a virtual function f in some class B is marked with the
virt-specifier final and in a class D derived from B a function
D::f overrides B::f, the program is ill-formed.
[ Example:
struct B {
virtual void f() const final;
};
struct D : B {
void f() const; // error: D::f attempts to override final B::f
};
—end example ]
A class may not be a derived class of itself. So the code you showed shall be compiled.
Also
5 If a virtual function is marked with the virt-specifier override and
does not override a member function of a base class, the program is
ill-formed.
[ Example:
struct B {
virtual void f(int);
};
struct D : B {
virtual void f(long) override; // error: wrong signature overriding B::f
virtual void f(int) override; // OK
};
—end example ]
In your example function Draw of class Circle is marked with virt-specidier override and indeed overrides the function of the base class.
This is a compiler bug. According to the grammar that the C++11 standard is specifying in [class.mem]:
member-declarator: declarator
virt-specifier-seqopt pure-specifieropt
declarator
brace-or-equal-initializeropt
identifieropt
attribute-specifier-seqopt : constant-expression
virt-specifier-seq:
virt-specifier
virt-specifier-seq
virt-specifier virt-specifier:
override
final
The virt-specifier-seq doesn't imply any order in the virt-specifiers in the declaration.
When we should use it in our program?
This question might be worth looking at.
It looks like Vlad from Moscow is correct
From the override specifier at cppreference.com:
declarator virt-specifier-seq(optional) function-body
In both cases, virt-specifier-seq, if used, is either override or final, or final override or override final.
And again for the final specifier at cppreference.com:
declarator virt-specifier-seq(optional) function-body
virt-specifier-seq, if used, is either override or final, or final override or override final.
Compiler bugs aside, I would encourage you to pick an order and stick to it consistently - don't mix and match the word order through your codebase.
Consider this snippet:
#include <iostream>
struct S {
virtual void pure1() = 0;
virtual void pure2() = 0;
};
struct T : S {
void pure1() { std::cout << "T::pure1" << '\n'; }
void pure2() { std::cout << "T::pure2" << '\n'; }
};
void S::pure2() { std::cout << "S::pure2" << '\n';}
int main()
{
T t;
t.S::pure2();
}
It prints S::pure2.
Looking at the C++11 Standard, I don't know exactly how does that happen. I believe it has to do with §3.4.5/4:
If the id-expression in a class member access is a qualified-id of
the form
class-name-or-namespace-name::...
the class-name-or-namespace-name following the . or -> operator is first looked up in the class of the object expression and the name, if
found, is used. Otherwise it is looked up in the context of the entire
postfix-expression.
But I don't understand how the pure virtual function pure2() is found in the base class S with the expression t.S::pure2(); above.
It is OK for a pure virtual function to be implemented in the base class. The standard specifies that to be valid (emphasis mine):
10.4 Abstract classes
2 An abstract class is a class that can be used only as a base class of some other class; no objects of an abstract class can be created except as subobjects of a class derived from it. A class is abstract if it has at least one pure virtual function. [ Note: Such a function might be inherited: see below. —end note ] A virtual function is specified pure by using a pure-specifier (9.2) in the function declaration in the class definition. A pure virtual function need be defined only if called with, or as if with (12.4), the qualified-id syntax (5.1).
If you didn't call
t.S::pure2();
then, it will be OK to omit implementation of S::pure2(). It will be a link time error if you didn't implement S::pure2() but still called
t.S::pure2();
The bit you're quoting covers the lookup of S in the expression t.S::pure2(). It doesn't apply to the name pure2 at all.
The relevant ruling here is 10.3/15:
Explicit qualification with the scope operator (5.1) suppresses the virtual call mechanism. [ Example:
class B { public: virtual void f(); };
class D : public B { public: void f(); };
void D::f() { /* ... */ B::f(); }
Here, the function call in D::f really does call B::f and not D::f. —end example ]
According to Wikipedia, in this example:
struct Base {
virtual void some_func(float);
};
struct Derived : Base {
virtual void some_func(float) override;
};
I thought override was not a C++ keyword, so what does it really mean?
We can achieve the same thing without that keyword so why would anyone need it?
There is also the keyword final which does not yet work on VS2010 :
struct Base1 final { };
struct Derived1 : Base1 { }; // ill-formed because the class Base1
// has been marked final
In C++11, override and final are "identifiers with special meaning". They are not keywords and only acquire special meaning if used in a specific context (when declaring virtual functions).
The idea is to enable to compiler to catch certain types of errors by allowing the programmer to explicitly state their intent (e.g. to override an existing virtual function rather than create a new one).
Here is the relevant quote from the standard, with examples:
C++11 10.3 4 If a virtual function f in some class B is marked with the
virt-specifier final and in a class D derived from B a function D::f
overrides B::f, the program is ill-formed. [ Example:
struct B {
virtual void f() const final;
};
struct D : B {
void f() const; // error: D::f attempts to override final B::f
};
—end example ]
5 If a virtual function is marked with the virt-specifier override
and does not override a member function of a base class, the program
is ill-formed. [ Example:
struct B {
virtual void f(int);
};
struct D : B {
void f(long) override; // error: wrong signature overriding B::f
void f(int) override; // OK
};
—end example ]
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.